本系列链接如下:
http://www.asp.net/learn/security/?lang=cs
Security Tutorials系列文章第一章:Security Basics and ASP.NET Support
本文英文原版:
http://www.asp.net/learn/security/tutorial-01-cs.aspx
导言:
论坛、电子商务网站等的一个共同点是什么呢?它们都提供用户帐户(user accounts).提供user accounts的站点都必须提供一系列的服务,至少新用户要能注册、注册的用户要能登陆.网站根据在线的用户作出这些抉择:某些页面或部分只能登陆用户或一部分用户才能访问.某些页面显示的内容要根据登陆的用户而定,比如只对登陆用户可见等.
本文是本系列的第一篇,在本系列我们将考察这些技术:通过web form来甄别用户,批准对某个具体页面或功能的访问,以及在ASP.NET application里管理用户帐户.贯彻该系列我们将考察:
.甄别用户
.通过ASP.NET的Membership framework来管理用户帐户
.创建、更新、删除用户帐户
.对登陆用户访问某个页面、目录或相关功能进行限制.
.通过ASP.NET的Roles framework将用户帐户和角色关联起来.
.管理用户角色.
.对角色访问某个页面、目录或相关功能进行限制.
.对ASP.NET的security Web controls进行定制以及扩展.
本系列通过很多的截屏来一步步地演示如何操作.每篇文章都分C#和Visual Basic 两个版本供下载(这第一篇主要从较高的视角来看待security概念,因此没有相关的代码供下载).
本文我们将考察一下比较重要的security概念,以及在ASP.NET里可以使用那些东西执行form验证,授权,用户帐户,角色等.
注意:
在任何跨技术的应用程序里Security都是很重要一个方面.对多方面的知识要求较高.本系列不是指导如何开发安全的web应用程序,相反仅仅专注于forms认证,授权,用户帐户和角色.有些与security相关的概念我们将在本系列探讨,其它的就没涉及了.
Authentication, Authorization, User Accounts, 以及Roles
Authentication, authorization, user accounts, 和roles在本系列里使用的很频繁,因此我花点时间从web security的角度进行解释说明.在一个客户端——服务器模式里,比如英特网,很多时候服务器要对发出请求的客户端进行确认.Authentication就是探明客户端身份的过程.客户端成功的通过了服务器确认的话,我们就可以说该客户端通过鉴别了(authenticated).未经确认的客户端可以叫做unauthenticated 或 anonymous(匿名).
Secure authentication systems至少要包括如下3方面之一: something you know, something you have,或something you are.绝大多数web应用程序都需要依赖客户端信息,比如,用户密码或个人身份号码(PIN).这些信息用来对用户进行确认——比如他的username 和 password——这又涉及到credentials.本系列仅关注forms authentication,这种认证模式需要用户在一个web页面表单(web page form)里提供他们的credentials.在以前我们都经历过这种类型的认证.在任何的电子商务网站,当你打算付账时,我们都需要在一个页面里将用户名和密码输入textboxes里再登陆.
除了对客户端进行确认外,我们还需要对客户端要访问的资源和功能进行一些限制.Authorization就是这样的一个过程:判断某个用户是否有访问某些特定资源或功能的权限.
user account是对某个用户的信息进行存储.User accounts最少要包含可以唯一的识别用户的信息,比如用户的登录名以及密码.除了这些最基本的信息外,user accounts还可能包括:用户的电子邮件,创建用户的日期和时间,用户最后一次登陆的时间,first name和last name,电话号码,通讯地址等.使用forms authentication时,用户帐户信息一般是存储在一个关系型数据库里,比如Microsoft SQL Server.
支持用户帐户的Web应用程序可以将用户任意划分成不同的角色.一个角色仅仅是一个应用于某个用户的标签,可以获取授权规则以及页面级的功能.比如,某个网站可能有一个“Administrator”角色,授权规则是,只有某个属于“Administrator”角色的用户才能访问某些特定的页面.此外,对那些所有人都可以访问的页面,如果是以Administrators角色进行访问的话还可以显示其它角色看不到的数据以及其它角色不能使用的功能.通过使用roles,我们就可以定义基于role,而不是基于user的规则.
在一个ASP.NET应用程序里鉴别用户
当一个用户在浏览器的地址栏输入一个URL或点击一个链接时,浏览器将向服务器发出一个a Hypertext Transfer Protocol (HTTP)请求,以请求指定的资源,它可能是一个ASP.NET page, 一个image,一个JavaScrips文件,或其它类型的资源. 服务器将返回指定的资源.这样我们必须对请求做一些判定,包括是谁发出的请求,是否通过了授权.
默认情况下,浏览器发出HTTP请求时并没有包含确认信息.但如果浏览器包含authentication
信息的话,服务器就开始启动authentication流程,它将对发出请求的客户端进行确认,authentication流程采取的步骤取决于应用程序使用的authentication类型.ASP.NET支持3种类型的authentication: Windows, Passport,以及forms. 本系列我们将关注forms authentication,不过我们先花点时间看看Windows authentication.
Windows Authentication认证
Windows authentication流程使用如下的认证技术之一:
.Basic authentication
.Digest authentication
.Windows Integrated Authentication
这3种技术的工作方式都一样:当未授权的、匿名的请求到达时,服务器将回送一个HTTP response,指出只有经过授权才能继续操作。浏览器然后显示一个对话框,要求用户输入用户名和密码(见图1),该信息然后经由一个HTTP header发回服务器.
提供的信息将与服务器的Windows User Store进行确认.这就意味着在应用程序里的每一个认证用户在组织机构都必须有一个Windows帐户. 这在企业内部网是很常见的.实际上,在企业内部网里使用Windows Integrated Authentication时,浏览器将自动的向服务器提供用于登陆网络的credentials,因此不会出现如图1所示的对话框.诚然,在企业内部网里使用Windows authentication是很方便可取的,但在英特网应用程序里这通常是难以实施的,因为你不可能向每一个用户每次登陆网站时都创建一个Windows帐户.
Forms Authentication认证
相反,Forms authentication是用来处理英特网应用程序的,记得我们说过forms authentication是将用户的credentials输入到一个web form来进行用户确认的.因此当一个用户试图访问一个未经授权的资源时,将会自动的转到一个登陆页面,以便登陆.提交的credentials将与一个用户定制存储——通常是一个数据库进行核对.
当提交的credentials通过验证后,将会为该用户创建一个表单验证票据(forms authentication ticket),该票据指出该用户已经通过验证,且包含识别信息,比如用户名.表单验证票据(一般)是存储为一个cookie,放在客户端机器上.因此,当再次访问网站时,在HTTP请求里就包含了该表单验证票据,web应用程序就可以识别出该用户曾经登陆过.
图2图解了authentication流程.注意,ASP.NET里的authentication 和 authorization模块扮演的是2个彼此独立的实体.forms authentication system对用户进行确认(或指出他们是匿名的),authorization system用来确定用户是否有权访问请求的资源.如果用户未经授权(比如图2里,匿名访问ProtectedPage.aspx页面),那么authorization system将指出用户被拒绝,导致forms authentication system自动的将用户导航到登陆页面.
我们将在接下来的二篇文章《An Overview of Forms Authentication》以及《Forms Authentication Configuration and Advanced Topics》里对forms authentication进行深入的探讨,对ASP.NET的authentication的更多详情,请参阅《ASP.NET Authentication》( http://msdn2.mirosoft.com/en-us/library/eeyk640h.aspx )
对Web Pages, Directories,以及Page Functionality的访问进行限制
ASP.NET有2种途径来判断是否某个特定用户有权访问一个指定的文件或目录:
.File authorization——由于ASP.NET pages和web services都是以服务器的文件系统里的文件为基础执行的.对这些文件的访问可以通过Access Control Lists (ACLs)来指定. File authorization通常是在Windows authentication里使用的,因为ACLs是与Windows帐户挂钩的当使用forms authentication时,所有的操作系统级以及文件系统级的请求都是以相同的Windows account来执行的,而与登陆的用户无关.
.URL authorization——当使用URL authorization时,页面开发者在Web.config文件里指定authorization rules,这些规则指明了哪些用户或角色被授权(或禁止)对特定的页面或目录进行访问.
File authorization和URL authorization对某个特定的ASP.NET页面或某个目录里所有的页面定义了访问规则,利用这些技术我们可以让ASP.NET拒绝某些用户对某个特定页面的请求,或只允许一部分用户访问.但还有这种情形,某个页面允许所有的用户访问,但页面所提供的功能却因用户的不同而不同.比如很多提供用户帐户的网站,有某些页面,匿名用户和登陆用户看到的数据和内容不一样,匿名用户看到的可能是一个登陆网站的链接,而登陆用户看到的可能是“Welcome back, Username” ,同时还有一个供注销的链接.还有一个例子:当登陆一个拍卖网站时,你看到的信息是不一样的,这取决于你是投标人还是拍卖人.
像这样的页面级的调整可以通过显式或编程的方式来实现.为了使匿名用户和验证用户看到的内容不同,我们可以拖一个LoginView控件到页面上,在AnonymousTemplate 和 LoggedInTemplate templates里分别输入恰当的内容. 此外,你也可以编程来判断当前的请求是否进过了认证,用户是谁?属于什么角色(如果有的话),然后你根据这些信息来决定来页面上显示或隐藏某些内容.
本系列有3篇文章是关注authorization的.《User-Based Authorization》考察了如何限制特定的用户帐户对一个页面或一个目录里所有页面的访问.《Role-Based Authorization》考察如何提供角色级的authorization rule.《Displaying Content Based on the Currently Logged In User》将考察如何根据登陆页面的用户来修改某个页面的内容和功能.更多详情请参阅《ASP.NET Authorization》
User Accounts and Roles
ASP.NET的forms authentication提供了一个基础构架(infrastructure)以便于用户登录站点,并在不同页面之间导航是不会丢失其认证状态(authenticated state).URL authorization提供了一个框架来限制对ASP.NET应用程序的某个文件或文件夹进行访问.除此之外,太提供了一个方法来存储帐户信息或管理角色.
在ASP.NET 2.0之前,开发人员需要自己定义的用户和角色存储(user and role stores).他们也需要自己设计用户接口、为那些与用户帐户相关的最基本的页面——比如登录页面、创建新帐户的页面——编写代码以处理相关逻辑.没有ASP.NET里内置的用户帐户框架,开发人员需要自己决定如何处理哪些与用户帐户相关的问题,比如“如何存储用户密码以及其它敏感的信息?”、“对密码的长度以及安全性采取何种措施?”.
今天,归功于Membership framework以及内置的Login Web controls控件,在ASP.NET应用程序里贯彻用户帐户变地简单多了.Membership framework就是 System.Web.Security namespace命名空间里的一系列类,这些类提供了处理用户帐户相关问题的一些函数方法.Membership framework里的一个关键类是Membership class, 它包括的方法有:
.CreateUser——创建用户
.DeleteUser——删除用户
.GetAllUsers——获取所有用户
.GetUser——获取用户
.UpdateUser——更新用户
.ValidateUser——验证用户
Membership framework使用的是provider模式,它将Membership framework的API与具体的程序执行分割开来.这就使开发人员可以使用一个常用的API,来满足某个应用程序具体的需求.简而言之,Membership class定义了框架的最基本的功能(方法、属性、事件等),但并没有指定具体的实施细节.相反,Membership class的方法调用配置好了的provider,由该provider实际执行.比如,当调用Membership class的CreateUser方法时,Membership class并不知道user store的具体细节,它不清楚帐户是存储在一个数据库,还是存储在一个XML文件,又或
是其它的什么存储方式.Membership class检查应用程序的配置以确定使用什么provider,由该provider在相应的user store里创建新用户帐户.在图3里用图表进行相应的阐述.
Microsoft在.NET Framework里提供了2种Membership provider classes:
.ActiveDirectoryMembershipProvider——在Active Directory以及Active Directory Application Mode (ADAM) servers里执行Membership API.
.SqlMembershipProvider——在一个SQL Server数据库里执行Membership API.
本系列文章将只关注SqlMembershipProvider.
图3
provider模式的好处在于,它可由微软,第三方开人商、或某些独立开发人员任意实施,并无缝的融入Membership framework.比如微软针对Access数据库发布了一个Membership provider.对该Membership providers的更多详情请参阅《Provider Toolkit》,它包括了各个Membership providers,简单的自定义providers,超过100页的关于provider模式的文档,以及内置的Membership provider(也就是ActiveDirectoryMembershipProvider 和 SqlMembershipProvider)的完整源代码.
ASP.NET 2.0同样引入了Roles framework,与Membership framework类似,Roles framework也采用provider模式.其API包含在Roles class,在.NET Framework提供了3个provider classes:
.AuthorizationStoreRoleProvider——在一个authorization-manager policy store里管理角色信息,比如Active Directory或ADAM.
.RoleProvider——在一个SQL Server数据库里贯彻roles
.WindowsTokenRoleProvider——将角色信息与登录者的Windows group关联起来,该方法典型的运用于Windows authentication.
本系列文章仅关注lRoleProvider.
由于provider模式包含的是相当独立的API(Membership以及Roles classes), 就使我们可以围绕这些API构建功能而不必担心具体的实施细节——由页面开发人员选定的provider来具体执行.这些统一了的API使得微软和第三方开发商可以创建接口面向Membership 和 Roles frameworks的Web控件.ASP.NET提供了很多的Login Web controls以执行常见的用户帐户相关的用户接口.比如,Login control揭示了用户的credential,进行验证,然后通过forms authentication使他们穿梭于网络.LoginView control使用模板为匿名用户和验证用户提供不同的显示界面,或根据用户角色的不同显示不同的界面.而CreateUserWizard control则为创建一个新用户帐户提供了一步步的创建界面.
各个Login controls都与Membership 和 Roles frameworks产生关联.绝大多数Login controls可以不用手写一行代码就可以运行.我们在后面的文章更详细的阐述这些控件,包括如何对它们的功能进行扩展和定制.
结语:
所有提供用户帐户的web应用程序面临的问题都差不多:比如运行用户登录,在页面之间导航时不丢失用户信息,需要一个创建新帐户的页面;要使页面开发人员指定对哪些用户或角色显示什么资源、数据、功能等.在对用户认证和授权,以及管理用户帐户和角色在ASP.NET应用程序里都是很容易实现的,这都要归功于forms authentication, URL authorization,以及Membership and Roles frameworks.
在接下来的系列文章里我们将通过按部就班的方式构建一个web应用程序以对这些方面进行探讨.在接下来的2篇文章里,我们将详细的探讨forms authentication,我们将实际的看到forms authentication工作流程,探讨表单验证票据(forms authentication ticket),探讨security相关事项,以及如何来配置forms authentication system——运行访问者登录以及注销.
祝编程快乐!
作者简介:
Scott Mitchell,著有七本ASP/ASP.NET方面的书,是4GuysFromRolla.com的创始人,自1998年以来一直应用 微软Web技术。Scott是个独立的技术咨询顾问,培训师,作家,最近完成了将由Sams出版社出版的新作,24小时内精通ASP.NET 2.0。他的联系电邮为 mitchell@4guysfromrolla.com ,也可以通过他的博客 http://ScottOnWriting.NET 与他联系。
Security Tutorials系列文章第一章:Security Basics and ASP.NET Support