l 综述
当某一个用户使用用户名成功登陆网站时,FormsAuthentication(窗体身份验证机制,下面统一使用英文术语) 将会创建一个authentication ticket (身份验证票),通过这个ticket就可以在网站上全程跟踪这个用户了。Form authentication ticket通常被包含在一个Cookie里面,但是Asp.net2.0也支持不使用Cookie的FormsAuthentication,这时候ticket就需要通过Query string 传递。
当一个用户在登陆某个网站时,需要提供身份验证才能进入网站。如果他还没有输入验证信息(通常是用户名和密码),则此用户将会被重定向到一个登陆页面。用户可以在登陆页面输入验证信息,然后这些信息被发送到服务器与某一个存储用户身份信息的介质(例如Sql Server或者某个文件)进行信息对比。在ASP.Net2.0中,可以通过MemberShip Proivder来访问存储在诸如Sqlserver的信息。(Provider模式有很多优点,稍后会有文章详细说明。)当用户信息通过验证后,此用户将获得允许,访问他所期望的页面。
FormsAuthentication通过FormsAuthenticationModule这个类来执行,这个类是ASP.net页面运行周期的一部分。以下我们将解释FormsAuthentication在ASP.net2.0中是如何工作的。
l IIS 验证
Asp.net验证分为两步。首先,IIS验证当前用户访问网站所使用的windows帐号是否有权限。如果IIS访问被配置为anonymous,则任何用户都能访问页面。
然后,在IIS验证完毕后,ASP.net开始执行自身的验证。验证模式可以在web.config文件中配置,只要在config文件中写上<authentication mode="Forms" />,那么ASP.net就知道使用FormsAuthenticationModule 类进行验证。
l Asp.Net Froms Authentication
Froms Authentication 配置:你可以在config文件中配置。配置如下:
<system.web>
<authentication mode="Forms">
<forms loginUrl="Login.aspx"
protection="All"
timeout="30"
name=".ASPXAUTH"
path="/"
requireSSL="false"
slidingExpiration="true"
defaultUrl="default.aspx"
cookieless="UseDeviceProfile" enableCrossAppRedirects="false" />
</authentication>
</system.web>
这些属性详细描述如下:
loginUrl:指向登陆页面,你应改把登陆页面放在一个需要Secure Sockets Layer (SSL)的文件夹里。这样才能保障帐号的安全和完整。
potection:设置为”ALL”表明authentication ticket是加密的,加密算法被定义在machineKey这个元素中,并且通过哈希算法进行签名,这个算法也定义在machineKey中。
timout:该属性定义了验证session的过期时间。默认值为30分钟。
RequireSSL:该属性被设置为false,这表明验证的cookies可以不同过SSL加密传输。如果对session的安全性特别重视的话,则需要设置为true。
slidingExpiration:该属性被设置为true,这表示用户只要在网站上持续保持活动,则session就不会过期。
DefaultUrl:该属性表示登陆后的默认页面。
Cookieless:该属性被设置为UseDeviceProfile,这表示cookie将在任何支持它的浏览器中使用,如果该浏览器不支持cookie的话,form authentication将通过url来传递authentication ticket
enableCrossAppRedirects:该属性表示是否可以将通过身份验证的用户重定向到其他web应用程序。True表示可以,False表示不可以。
l Authorization Configuration(用户配置)
类UrlAuthorizationModule用来执行保障只有通过身份验证的用户才能访问页面。你可以在web.config文件中配置这个类:配置如下:
<ystem.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
以上配置表明,没有通过验证的用户都将被拒绝访问页面。如果一个没有验证的用户试图访问页面,他将会被重定向到loginUrl属性定义的登陆页面上。
l Forms Authentication 控制流程
Forms Authentication的流程可以参考下图:
我们来分析一下上面的流程:
第一步:用户访问default.aspx页面,IIS通过了验证,ASP.Net发现 authorization
元素中包含<deny users="?" />的标签。
第二步:服务器寻找包含验证信息的cookie,如果没有找到这个cookie,用户将被重定向到登陆页面。就是loginurl所指定的页面。用户将在那个页面输入登陆信息。:
第三步:浏览器请求浏览登录页面,同时传递ReturnUrl的参数的值。
第四步:服务器调转到登陆页面。
第五步:用户输入身份验证信息,并且提交数据,其中还包含ReturnUrl的参数值。
第六部:服务器通过读取存储介质(例如sqserver数据库)验证用户的信息。登陆页面将创建一个包含form authentication ticket的cookie作为session。
在Asp.net2.0身份验证可以通过membership系统。Membership类提供了ValidateUser的方法,参考如下:
if (Membership.ValidateUser(userName.Text, password.Text))
{if (Request.QueryString["ReturnUrl"] != null) {FormsAuthentication.RedirectFromLoginPage(userName.Text,false); }
else { FormsAuthentication.SetAuthCookie(userName.Text, false); } }
else { Response.Write("Invalid UserID and Password");
}
第七步:用户验证成功,服务器重新让浏览器指向ReturUrl所指定的页面。
第八步:在重定向的同时,浏览器向default.aspx页面发送request请求,此次请求包含用户的forms authentication cookie。
第九步:FormsAuthenticationModule类侦测到forms authentication cookie并且开始验证,验证成功后,该类将得到当前的用户信息,并传送给HttpContext对象。可以通过HttpContext对象获得当前用户的信息。
第10步:验证成功,来去自如哦!
l FormsAuthenticationModule
ASP.Net 2.0在系统默认的web.config文件中定义了一系列的Http模块(Http Modules).其中包括了一系列的验证模块如下:
<httpModules>
...
<add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" />
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
<add name="PassportAuthentication" type="System.Web.Security.PassportAuthenticationModule" /> ... </httpModules>
在每一次请求时,只能使用一种验证模块。通常验证模式会被定义在web.config文件中:
<authentication mode="Forms" />这句话表示使用FormsAuthentication
FormsAuthenticationModule类会创建一个GenericPrincipal的对象,然后把它存入Http Context中。GenericPrincipal包含一个FormsIdentity的实例的引用,FormsIdentity实例包含了用户的信息。一般你会通过forms authentication来替你完成以上工作。但是如果你的程序还有别的特殊要求,比如把用户信息传递给一个自定义的类(该类继承IPrincipal接口),你的程序需要在PostAuthenticate Event事件中编写代码。PostAuthenticate Event事件会在 FormsAuthenticationModule验证forms authentication cookie 并且创建完GenericPrincipal和FormsIdentity对象后触发,在该事件触发后,你可以在事件中创建自定义的IPrincipal对象,用此对象封装FormsIdentity对象,然后把自定义的IPrincipal对象存入HttpContext中。
注意:如果自定义IPricipal对象,你必须在当前线程中设置自定义对象的引用:例如:Thread.CurrentPrincipal=newGenericPrincipal(new GenericIdentity( "Bob", "Passport"), rolesArray);
这样才能保证HttpContext对象和线程指向同一个验证用户的信息。
l Forms Authentication Cookies
FormsAuthentication类在调用FormsAuthentication.SetAuthCookie或者FormsAuthentication.RedirectFromLoginPage的方法后会自动创建验证Cookie;
一个典型的验证cookie包含以下两个属性:
Name:Cookie的名称
Value:Cookie的值
在一个典型的forms authentication cookie中,cookie的值是加密的,并且创建一个FormAuthenticationTicket的签名。Cookie包含以下属性:
Expires:此属性标识cookie的过期时间,当用户需要把cookie保存在本地电脑上时,需要设置此属性。
Domain:这个属性表明cookie和哪个域相关联,默认的值为null
HasKeys:这个属性表明cookie是否有子键。
HttpOnly: 这个属性表示cookie是否能被客户端脚本读取,.net2.0中,这个设置始终为true;但在客户端浏览器中,只有IE6.0才能识别这个属性。
Path:这个属性表明cookie的虚拟目录。默认的值为”/”,表示站点根目录。
Secure:这个属性表明cookie是否需要加密。如果设置true,cookie将接受SSL加密
Version:这个属性表明cookie的版本号
l 创建Forms Authentication Cookies
当某个用户验证通过后,Forms Authentication Cookies会被Forms Authentication类在内部自动创建。创建的就是一个FormsAuthenticationTicket类。创建此类的代码如下:
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
"userName",
DateTime.Now,
DateTime.Now.AddMinutes(30), // value of time out property false, // Value of IsPersistent property
String.Empty,
FormsAuthentication.FormsCookiePath);
然后如果在web.config文件中,forms元素的protection属性被设置成ALL
或者Encryption,将对ticket对象进行加密并且创建签名。加密代码如下:
string encryptedTicket = FormsAuthentication.Encrypt(ticket);