Forms 认证
学习于:http://www.cnblogs.com/fish-li/archive/2012/04/15/2450571.html
在ASP.NET中,整个身份认证的过程其实可分为二个阶段:认证与授权。
1. 认证阶段:识别当前请求的用户是不是一个可识别(的已登录)用户。
2. 授权阶段:是否允许当前请求访问指定的资源。
这两个阶段在ASP.NET管道中用AuthenticateRequest和AuthorizeRequest事件来表示。
a.在认证阶段,ASP.NET会检查当前请求,根据web.config设置的认证方式,尝试构造HttpContext.User对象供我们在后续的处理中使用。
b.在授权阶段,会检查当前请求所访问的资源是否允许访问,因为有些受保护的页面资源可能要求特定的用户或者用户组才能访问。 所以,即使是一个已登录用户,也有可能会不能访问某些页面。当发现用户不能访问某个页面资源时,ASP.NET会将请求重定向到登录页面。
c.受保护的页面与登录页面我们都可以在web.config中指定
3.在ASP.NET中,Forms认证是由FormsAuthenticationModule实现的,URL的授权检查是由UrlAuthorizationModule实现的。
4.在web.config中配置Forms认证:
<authentication mode="Forms"> <forms name="UserStates" cookieless="UseCookies" loginUrl="Login.aspx"></forms> </authentication>
Forms认证是基于cookie的,这里的name="UserStates"就是这个cookie的名字,名字可以随便取,通过Fiddler就可以看见,asp.net会为已登录的用户创建一个身份验证信息,而这个验证信息经加密后就保存在name="UserStates"这个cookie中,未登录的用户是没有这个验证信息的,然后就可以通过
Request.IsAuthenticated?"已登录":"未登录";//来判断当前用户是否已经登录
其中loginUrl="Login.aspx"是配合授权【Authorization】使用的,即如果用户A在未登录的情况下访问MyPage.aspx,而MyPage.aspx只对已登录用户可见,则此时url会跳转到loginUrl指定的Login.aspx
【Authorization】在web.config中的简单配置:
<location path="MyPage.aspx"> <system.web> <authorization> <deny users="?"/> </authorization> </system.web> </location>
创建保存验证信息的cookie调用的方法是:
FormsAuthentication.SetAuthCookie(userName, true);//传递用户名即可
然后通过HttpContext.Current.User.Identity.Name可以在其他page类中获取当前已登录用户的用户名
调用FormsAuthentication.SignOut();可以实现注销功能
代码小例子:
A.Login.aspx
<form id="form1" runat="server" action="FormAuthentication.ashx" method="post"> <div> 用户名: <input id="Text1" type="text" name="name" /> <br /> 密码:<input id="Text2" type="password" name="pwd" /> <br /> <input id="Submit1" type="submit" value="submit" /> </div> </form>
B.FormAuthentication.ashx
public class FormAuthentication : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; String uName = context.Request.Form["name"]; String uPwd = context.Request.Form["pwd"]; if (uPwd == "123123") { FormsAuthentication.SetAuthCookie(uName, false); context.Response.Redirect("~/WebForm2.aspx"); //context.Response.Redirect("~/mypage.aspx"); } else { context.Response.Write("用户名或密码错误"); } } public bool IsReusable { get { return false; } } }
C.WebForm2.aspx部分代码
protected void Page_Load(object sender, EventArgs e) { if (Request.IsAuthenticated) { this.Label1.Text = "已登录"; this.Label2.Text = HttpContext.Current.User.Identity.Name; } else { this.Label1.Text = "未登录"; } }
5.在web.config中配置受保护的页面:
在一个ASP.NET网站中,有些页面会允许所有用户访问,包括一些未登录用户,但有些页面则必须是已登录用户才能访问, 还有一些页面可能会要求特定的用户或者用户组的成员才能访问。这类页面因此也可称为【受限页面】,它们一般代表着比较重要的页面,包含一些重要的操作或功能。
为了保护受限制的页面的访问,ASP.NET提供了一种简单的方式: 可以在web.config中指定受限资源允许哪些用户或者用户组(角色)的访问,也可以设置为禁止访问。
如:网站中的一个页面:MyPage.aspx,只允许已登录用户可访问,那么可在web.config中配置做如下配置:
<location path="MyPage.aspx"> <system.web> <authorization> <deny users="?"/> </authorization> </system.web> </location>
为了方便,我可能会将一些管理相关的多个页面放在Admin目录中,显然这些页面只允许Admin用户组的成员才可以访问。 对于这种情况,我们可以直接针对一个目录设置访问规则:
<location path="Admin"> <system.web> <authorization> <allow roles="Admin"/> <deny users="*"/> </authorization> </system.web> </location>
这样就不必一个一个页面单独设置了,还可以在目录中创建一个web.config来指定目录的访问规则
在allow和deny的配置中,我们可以在一条规则中指定多个用户:
1). 使用users属性,值为逗号分隔的用户名列表。
2). 使用roles属性,值为逗号分隔的角色列表。
3). 问号 (?) 表示匿名用户。
4). 星号 (*) 表示所有用户。
6.小结:
Form身份认证依赖Cookie,由于登录状态是保存在Cookie中,而Cookie又会保存到客户端,因此,为了保证登录状态不被恶意用户伪造, ASP.NET采用了加密的方式保存登录状态。为了实现安全性,ASP.NET采用【Forms身份验证凭据】(即FormsAuthenticationTicket对象)来表示一个Forms登录用户, 加密与解密由FormsAuthentication的Encrypt与Decrypt的方法来实现。Asp.net就是每次检查我们在配置文件中指定的Cookie名称,并解密这个Cookie来判断当前请求用户的登录状态。
用户登录的大致过程:
1. 检查用户提交的登录名和密码是否正确。
2. 根据登录名创建一个FormsAuthenticationTicket对象。
3. 调用FormsAuthentication.Encrypt()加密。
4. 根据加密结果创建登录Cookie,并写入Response。
在登录验证结束后,一般会产生重定向操作, 那么后面的每次请求将带上前面产生的加密Cookie,供服务器来验证每次请求的登录状态。
每次请求时的(认证)处理过程:
1. FormsAuthenticationModule尝试读取登录Cookie。
2. 从Cookie中解析出FormsAuthenticationTicket对象。过期的对象将被忽略。
3. 根据FormsAuthenticationTicket对象构造FormsIdentity对象并设置HttpContext.User
4. UrlAuthorizationModule执行授权检查。
通过直接调用SetAuthCookie方法来实现Forms认证的方式只能传递一个登录名,但是有时候为了方便后续的请求处理,还需要保存一些与登录名相关的额外信息【用户信息】,这时就得要实现自定义的身份认证标识来实现这一功能了。