Asp.Net 基础知识回顾_认证授权
ASP.NET使用HTTP管道模型来处理HTTP请求,当一个HTTP请求到达Web服务器时,这个请求按“HttpModule >>Page/HttpHandle >>HttpModule”这样的顺序先后通过各个HttpModule和Page/HttpHandle对象,在这些对象中将触发应用程序事件。事件的触发顺序如下图所示。
从上图可以看到,在触发页面事件(即正式对页面进行处理)之前,将先触发Application_AuthenticateRequest、Application_PostAuthenticateRequest、Application_AuthorizeRequest、Application_PostAuthorizeRequest这四个事件,通过这四个事件,我们可以自定义用户身份验证,再进行正式的页面处理。
1. AuthenticateRequest事件
当安全模块已建立用户标识时发生。AuthenticateRequest事件发出信号表示配置的身份验证机制已对当前请求进行了身份认证,预订AuthenticateRequest事件可确保在处理附加的模块或事件处理程序之前对请求进行身份认证。
2. PostAuthenticateRequest事件
当安全模块已建立用户标识时发生。有时我们使用成员组Context.User及Forms验证来实现用户的登录,但是成员组所提供的功能有限,当需要能访问到自己定义的个人信息时,这时我们就能利用此事件来处理。
3. AuthorizeRequest事件
当安全模块已验证用户授权时发生。AuthorizeRequest事件发出信号表示ASP.NET已对当前请求进行了授权。预订AuthorizeRequest事件可确保在处理附加的模块或事件处理程序之前对请求进行身份验证和授权。
4.PostAuthorizeRequest事件
在当前请求的用户已获授权时发生。PostAuthorizeRequest事件发出信号表示ASP.NET已对当前请求进行了授权。预订PostAuthorizeRequest事件可确保在处理附加的模块或处理程序之前对请求进行身份验证和授权。
一、Form登录
ASP.NET Forms身份验证方式通常使用Cookie来存储用户的身份验证票。用户通过身份认证后,可以将用户身份信息保存到客户端Cookie,当用户再次访问其他页面时,先将Cookie发送到服务器端,服务器端负责读取该Cookie中存放的用户信息。
二、Forms身份验证的工作原理
当向拒绝匿名用户访问的资源发出请求,并且当Forms身份验证处于激活状态时,URL授权模块就会把用户重定向到登录页面。原始请求的URL被保存为URL参数,方便以后使用。
登录页面是一个供用户输入凭证(通常指用户名和密码)的页面。如果用户输入的是正确的资料,就会创建一个“身份验证票证”。身份验证票证中含有经过加密的用户资料,这个票证将被写入Cookie并被发送到客户端,存放在用户的硬盘上,然后用户会被重定向到他们最初请求的URL。
用户再次请求原始URL时(因为被重定向回URL),身份验证票证Cookie会被浏览器添加到请求中,并被Forms身份验证模块获取。它利用Cookie中的资料填充Context.User属性(该属性将在下文详细介绍)。而URL授权模块则会利用这个用户信息来验证用户是否已被批准访问所请求的资源。
当然,我们还可以不使用拒绝访问——登录页面——接受访问这一过程来对用户进行身份验证。通常情况下,用户可以利用链接进入登录页面而不是被自动重定向到那个页面。这些情况下,身份验证票证被创建,并像对待强行进行的身份验证那样,把它保存为一个Cookie。
三、Forms身份验证的对象模型
ASP.NET安全架构为实现Web应用程序的完善的安全模式提供了一个对象模型。登录到应用程序的用户根据他们提供的凭证被授予了Principal和Identity。Principal对象表示的是用户的当前安全上下文,包括用户的标识和他们所属的角色。Identity对象表示的是当前用户。Principal对象是利用Identity对象(表示用户的标识)创建的,它添加了一些额外信息,比如角色或自定义应用程序数据。
四、Principal对象
Principal对象表示的是通过身份验证的用户的组或角色成员,也就是当前用户的安全上下文。Principal对象在当前HttpContext中可以被理解为User属性。HttpContext.Current.User属性返回的是一个IPrincipal实例,可以实现IPrincipal接口的对象。
(1) IPrincipal接口
不同的身份验证模式对安全上下文有不同的要求。我们可以利用Principal对象协调地表示当前的Principal(安全上下文)。IPrincipal接口可以定义Principal对象的基本功能。所有Principal对象都必需实现IPrincipal——System.Security.Principal命名空间的一部分。IPrincipal接口的成员如下所示:
名称 |
类型 |
描述 |
Identity |
属性 |
获取当前Principal对象的Identity对象 |
IsInRole(string roleName) |
方法 |
可以判断当前Principal对象是否属于指定的角色。 |
(2)GenericPrincipal类
GenericPrincipal类定义了IPrincipal接口的大部分基本实现,命名空间为System. Security.Principal。我们可以创建一个在当前请求的整个生命周期中都要使用的GenericPrincipal类实例,并把它赋值给HttpContext.Current.User属性。GenericPrincipal的构造函数如下所述:
//identity:实现了IIdentity接口的对象;roles:表示角色的字符串数组
public GenericPrincipal ( IIdentity identity, string[] roles)
GenericPrincipal类中的IslnRole方法通过把角色值和在字符串数组中定义的角色进行比较来判断当前用户的角色是否合法。
2. Identity对象
Identity对象用于表示当前用户的标识,即表示一个用户是否通过身份验证。在当前上下文环境中,可以通过HttpContext.Current.User.Identity.Name属性获取Identity对象。
(1) IIdentity接口
所有的Identity对象都必须实现IIdentity接口。与IPrincipal接口一样,IIdentity接口也定义在System.Security.Principal命名空间下面,它的成员如下所示:
名称 |
类型 |
描述 |
AuthenticationType |
属性 |
获取所使用身份验证的类型,即Forms身份验证、Windows身份验证、PassPort身份验证。 |
IsAuthenticated |
属性 |
获取一个值,该值指示是否验证了用户。 |
Name |
属性 |
获取当前用户的名称。 |
(2) FormsIdentity 类
FormsIdentity类表示一个使用Forms身份验证进行了身份验证的用户标识,命名空间为System.Web.Security。FormsIdentity类由FormsAuthenticationModule(ASP.NET内置的身份验证模块)在通过Forms身份验证对用户进行身份验证时使用。使用从Forms身份验证Cookie或URL解密的 FormsAuthenticationTicket(身份验证票据)创建一个FormsIdentity的实例。然后,使用此FormsIdentity类的新实例构造一个新的GenericPrincipal对象,该对象将设置为当前HttpContext的User属性的值。 FormsIdentity的构造函数:
//ticket:此标识所基于的身份验证票。 //类型:System.Web.Security.FormsAuthenticationTicket public FormsIdentity( FormsAuthenticationTicket ticket )
下表列出了FormsIdentity类中几个常用的属性。
名称 |
描述 |
AuthenticationType |
获取经过身份验证的标识的类型。 |
IsAuthenticated |
获取一个指示是否发生了身份验证的值。 |
Name |
获取Forms标识的用户名。 |
Ticket |
获取Forms身份验证用户标识的FormsAuthenticationTicket。 |
我们可以看到,FormsIdentity在IIdentity接口的基础上又增加了Ticket属性,这个属性提供了Forms身份验证票证,这样我们就可以在自定义的Forms身份验证中获取这个票证。
五、 Forms身份验证的API
1. FormsAuthentication类
FormsAuthentication类用于辅助我们完成窗体验证,并进一步完成用户登录等功能。该类位于System.Web.dll程序集的System.Web.Security命名空间中。通常在Web站点项目中可以直接使用这个类,如果是在类库项目中使用这个类,请确保引用了System.Web.dll。下表列出了FormsAuthentication类的常用属性。
属性 |
描述 |
DefaultUrl |
获取在没有指定重定向URL时FormsAuthentication类将重定向到的URL。 |
获取用于存储Forms身份验证票证的Cookie 名称。 |
|
获取 Forms 身份验证 Cookie 的路径。 |
|
获取 FormsAuthentication 类将重定向到的登录页的 URL。 |
FormsAuthentication还提供了两个重要的方法,分别是Encrypt和Decrypt,顾名思义,这两个方法分别提供了对身份验证票据的加密和解密的功能。
Encrypt方法创建一个字符串,其中包含适用于HTTP Cookie的加密的Forms身份验证票证。该方法是静态方法,可以通过以下方式调用。
//参数newAuthTicket:用于创建加密的 Forms 身份验证票证的 FormsAuthenticationTicket 对象。 //返回值:一个字符串,其中包含加密的 Forms 身份验证票证。 string cookieValue = FormsAuthentication.Encrypt(newAuthTicket); Decrypt方法创建一个FormsAuthenticationTicket对象,此对象将根据传递给该方法的加密的Forms身份验证票证而定。与Encrypt一样,该方法也定义为静态方法,调用方式如下所示。 //参数authCookie.Value:一个HttpCookie,表示加密的身份验证票 //返回值:解密后的身份验证票 FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
2. FormsAuthenticationTicket类
前面我们已经讲过,身份验证票证是经过加密并作为HTTP Cookie保存在各个请求之间的信息。票证主要用于支持Forms身份验证模块检验用户是否已经通过验证。
FormsAuthenticationTicket实例中含有我们希望维持的未加密格式的用户信息,我们可以通过一组属性访问该信息。可以通过三个重载的构造函数来实例化FormsAuthenticationTicket类,具体使用哪个构造函数需要根据实际需求而定,构造函数的定义如下表所示。
名称 |
描述 |
public FormsAuthenticationTicket ( string name, bool isPersistent, int timeout) |
使用cookie名和过期信息初始化 FormsAuthenticationTicket 类的新实例。 |
public FormsAuthenticationTicket ( int version,string name,DateTime issueDate, DateTime expiration, bool isPersistent, tring userData) |
使用Cookie名、版本、过期日期、发布日期、持久性以及用户特定的数据初始化FormsAuthenticationTicket类的新实例。Cookie路径设置为在应用程序的配置文件中建立的默认值。 |
public FormsAuthenticationTicket ( int version, string name, DateTime issueDate, DateTime expiration, bool isPersistent,string userData,string cookiePath) |
使用cookie名、版本、目录路径、发布日期、过期日期、持久性以及用户定义的数据初始化 FormsAuthenticationTicket类的新实例。 |
参数说明:
version: 票证的版本号。
name:与身份验证票关联的用户名。
issueDate:票证发出时的本地日期和时间。
expiration:票证过期时的本地日期和时间。
isPersistent:如果票证将存储在持久性Cookie(跨浏览器会话保存),则为true;否则为false。如果该票证存储在URL中,将忽略此值。
userData:存储在票证中的用户特定的数据。
cookiePath:票证存储在Cookie中时的路径。
FormsAuthenticationTicket类还提供了一套完整的与上面的参数对应的属性,如下表所示。
名称 |
描述 |
CookiePath |
获取Forms身份验证票证的Cookie 路径。 |
Expiration |
获取Forms身份验证票证过期时的本地日期和时间。 |
Expired |
获取一个值,它指示Forms身份验证票证是否已过期。 |
IsPersistent |
获取一个值,该值指示包含Forms身份验证票证信息的Cookie是否为持久性的。 |
IssueDate |
获取最初发出Forms身份验证票证时的本地日期和时间。 |
Name |
获取与Forms身份验证票相关联的用户名。 |
UserData |
获取一个存储在票证中的用户特定的字符串。 |
Version |
获取票证的版本号。 |
六、配置Forms身份验证
使用Forms身份验证之前,需要正确地配置web.config,包括两个元素:<authentication/>和<authorization/>。
1. <authentication/>元素
<authentication/>元素只能在应用程序根文件夹中的web.config中使用。试图在子文件夹中使用这个元素只会引发错误。这就表明,每个应用程序只能定义一个身份验证类型,如果我们希望在子文件夹中使用一个不同的身份验证类型,就必须把它定义为一个独立的应用程序。在Forms身份验证中,<authentication/>的配置通常会像这样:
<system.web> <authentication mode="Forms"> <forms loginUrl="~/User/Login.aspx" name=".ASPXAUTH" defaultUrl="User/Default.aspx" timeout="30" path="/" /> </authentication> </system.web>
下表说明了各个属性的作用。
名称 |
说明 |
mode |
必选的属性。 指定应用程序的默认身份验证模式。 有四个可选值,分别是Forms、Windows、Passport、None |
loginUrl |
可选的属性。 指定如果找不到任何有效的身份验证Cookie,将请求重定向到的用于登录的URL。 |
name |
可选的属性。 指定要用于身份验证的HTTP Cookie。如果正在一台服务器上运行多个应用程序并且每个应用程序都需要唯一的Cookie,则必须在每个应用程序的web.config文件中配置Cookie名称。 默认值为 ".ASPXAUTH"。 |
defaultUrl |
可选的属性。 定义在身份验证之后用于重定向的默认URL。 |
timeout |
可选的属性。 指定Cookie过期前逝去的时间(以整数分钟为单位)。 |
path |
可选的属性。 为应用程序发出的Cookie指定路径。 默认值是斜杠 (/),这是因为大多数浏览器是区分大小写,如果路径大小写不匹配,浏览器不会送回Cookie。 |
2. <authorization/>元素
<authorization/>元素针对授权进行配置,可以通过该元素指定应用程序某个目录的访问权限。该元素的格式一般如下面所示: <system.web> <authorization> <allow users="*" /> <deny users="?" /> </authorization> </system.web>
allow: 向授权规则映射添加一条允许对资源的访问的授权规则。
deny:向授权规则映射添加一条拒绝对资源的访问的授权规则。
users:必选的String属性。一个逗号分隔的用户名列表,这些用户名被拒绝对资源进行访问。问号(?)表示拒绝匿名用户,星号(*)表示拒绝所有用户帐户访问。
七、 实现Forms身份验证的基本流程
总的来说,Forms身份验证可分为两大块:认证与授权。具体步骤如下所示。
1. 认证
- 在登录页面的后置代码中判断用户名和密码是否合法,如果合法,则实例化一个Principal对象,并将用户信息(用户名、密码、角色、地址等)保存到Principal对象中。
- 使用FormsAuthenticationTicket类创建一个用户身份验证票。
- 调用FormsAuthentication.Encrypt加密FormsAuthenticationTicket。
- 以加密的FormsAuthenticationTicket字符串作为参数实例化HttpCookie实例。
- 以HttpCookie实例作为参数调用HttpContext.Current.Response.Cookies.Add方法将Cookie添加到客户端
2. 授权
- 在应用程序生命周期的Application_AuthenticateRequest事件中使用FormsAuthentication.FormsCookieName获取Cookie名称。
- 使用HttpContext.Request.Cookies[cookieName]获取Cookie值。
- 以Cookie值作为参数调用FormsAuthentication.Decrypt解密Cookie,生成用户身份票据FormsAuthenticationTicket。
- 依据FormsAuthenticationTicket重新生成Principal对象,并将Principal对象赋值给HttpContext.User。
- 在页面的Page_Load事件中使用HttpContext.User.Identity.IsAuthenticated验证用户是否身份是否合法。
八、移除不必要的身份验证模块
ASP.NET默认集成了提供Windows身份验证、Passport身份验证等功能的HttpModule,如果我们使用了Forms身份验证方式,则需要移除这些不必要的模块。具体如下所示。
<httpModules> <remove name="WindowsAuthentication" /> <remove name="PassportAuthentication" /> <remove name="FileAuthorization" /> <remove name="AnonymousIdentification" /> </httpModules>
九、简单案例
有空再完善!是在登录的时候返回验证票,请求的时候在AuthenticateRequest 事件中获取验证票解密就可以了!