虽然HTTP协议与WEB服务器是无状态,但我们的业务需求却要求有状态,典型的就是用户登录,在这种业务需求中,要求WEB服务器端能区分某个请求是不是一个已登录用户发起的,或者当前请求是哪个用户发出的。在开发WEB应用程序时,我们通常会使用Cookie来保存一些简单的数据供服务端维持必要的状态。既然这是个通常的做法,那我们现在就来看一下现在页面的Cookie使用情况吧,以下是我用FireFox所看到的Cookie列表:
498)this.width=498;'' onmousewheel = ''javascript:return big(this)'' alt="" src="/uploadfile/201301/5/74151246808.png" />
这个名字:LoginCookieName,是我在web.config中指定的:
- <authentication mode="Forms" >
- <forms cookieless="UseCookies" name="LoginCookieName" loginUrl="~/Default.aspx"></forms>
- </authentication>
在这段配置中,我不仅指定的登录状态的Cookie名,还指定了身份验证模式,以及Cookie的使用方式。
为了判断这个Cookie是否与登录状态有关,我们可以在浏览器提供的界面删除它,然后刷新页面,此时页面的显示效果如下:
498)this.width=498;'' onmousewheel = ''javascript:return big(this)'' alt="" src="/uploadfile/201301/5/02151246875.png" />
此时,页面显示当前用户没有登录。
为了确认这个Cookie与登录状态有关,我们可以重新登录,然后再退出登录。
发现只要是页面显示当前用户未登录时,这个Cookie就不会存在。
事实上,通过SetAuthCookie这个方法名,我们也可以猜得出这个操作会写一个Cookie。
注意:本文不讨论无Cookie模式的Forms登录。
从前面的截图我们可以看出:虽然当前用户名是 Fish ,但是,Cookie的值是一串乱码样的字符串。
由于安全性的考虑,ASP.NET对Cookie做过加密处理了,这样可以防止恶意用户构造Cookie绕过登录机制来模拟登录用户。如果想知道这串加密字符串是如何得到的,那么请参考后文。
小结:
1. Forms身份认证是在web.config中指定的,我们还可以设置Forms身份认证的其它配置参数。
2. Forms身份认证的登录状态是通过Cookie来维持的。
3. Forms身份认证的登录Cookie是加密的。
理解Forms身份认证
经过前面的Cookie分析,我们可以发现Cookie的值是一串加密后的字符串,现在我们就来分析这个加密过程以及Cookie对于身份认证的作用。
登录的操作通常会检查用户提供的用户名和密码,因此登录状态也必须具有足够高的安全性。在Forms身份认证中,由于登录状态是保存在Cookie中,而Cookie又会保存到客户端,因此,为了保证登录状态不被恶意用户伪造, ASP.NET采用了加密的方式保存登录状态。为了实现安全性,ASP.NET采用【Forms身份验证凭据】(即FormsAuthenticationTicket对象)来表示一个Forms登录用户,加密与解密由FormsAuthentication的Encrypt与Decrypt的方法来实现。
用户登录的过程大致是这样的:
1. 检查用户提交的登录名和密码是否正确。
2. 根据登录名创建一个FormsAuthenticationTicket对象。
3. 调用FormsAuthentication.Encrypt()加密。
4. 根据加密结果创建登录Cookie,并写入Response。
在登录验证结束后,一般会产生重定向操作,那么后面的每次请求将带上前面产生的加密Cookie,供服务器来验证每次请求的登录状态。
每次请求时的(认证)处理过程如下:
1. FormsAuthenticationModule尝试读取登录Cookie。
2. 从Cookie中解析出FormsAuthenticationTicket对象。过期的对象将被忽略。
3. 根据FormsAuthenticationTicket对象构造FormsIdentity对象并设置HttpContext.Usre
4. UrlAuthorizationModu