Cookie的作用很大,在很多技术方案中都有应用。它也是Forms身份认证模式所使用的一门技术点。
今天我就说一说它在Forms身份认证模式中都起到什么作用。
(一)理论知识
ASP.NET 使用身份验证提供程序实现附加的身份验证方案,这些身份验证提供程序独立于 IIS 身份验证方案并且只用于 IIS 身份验证方案之后。ASP.NET 支持下列身份验证提供程序:
- Windows(默认)
- Forms
- Passport
- None
若要启用 ASP.NET 应用程序的身份验证提供程序,请使用 machine.config 或 Web.config 中的身份验证元素,如下所示:
-
<system.web> <!-- mode=[Windows|Forms|Passport|None] --> <authentication mode="Windows" /></system.web>
每个 ASP.NET 身份验证提供程序都支持 OnAuthenticate 事件,该事件在身份验证过程中发生,您可以使用该事件实现自定义的身份验证方案。该事件的主要目的是将实现 IPrincipal 接口的自定义对象附加到上下文中
上面引用了MSDN中的定义。
二:Forms身份认证
Forms 身份验证提供程序是一个身份验证方案,它使应用程序可使用 HTML 窗体直接从客户端收集凭据。客户端直接向应用程序代码提交凭据以进行身份验证。如果应用程序验证该客户端的身份,则它向该客户端发出一个 cookie,该客户端在后面的请求中提交该 cookie。如果对于受保护资源的请求不包含该 cookie,则应用程序将该客户端重定向到登录页。当验证凭据时,应用程序可以用多种方法存储凭据,如配置文件或 SQL Server 数据库。有关更多信息,请参见 Forms 身份验证提供程序。
注意 ISAPI 服务器扩展仅处理那些它拥有其应用程序映射的资源。例如,ASP.NET ISAPI 服务器扩展仅拥有特定资源(如 .asax、ascx、.aspx、.asmx 和 .config 文件,这里只给出这几个)的应用程序映射。默认情况下,ASP.NET ISAPI 服务器扩展以及随后的 Forms 身份验证提供程序不处理任何对非 ASP.NET 资源(如 .htm、.jpg 或 .gif 文件)的请求。
优点
- 允许使用任意条件自定义身份验证方案。
- 可用于身份验证或身份确认。
- 不需要相应的 Windows 帐户。
缺点
- 受制于 cookie 生存期的重放攻击,除非使用 SSL/TLS。
- 仅适用于映射到 Aspnet_isapi.dll 的资源。
同样引用MSDN,接下来就用具体代码实现其功能。
(三)一步一步实现Form认证模式
第一步:配置
在Web.Config中配置如下
<system.web>
<authentication mode="Forms">
<forms cookieless="UseCookies" name="LoginCookieName" loginUrl="Login.aspx"></forms>
</authentication>
</system.web>
第二:设置登录凭证
新建立页面Login.aspx,代码如下
前台
1 <table> 2 <tr> 3 <td>登录名:</td> 4 <td><asp:TextBox ID="txtName" runat="server"></asp:TextBox></td> 5 </tr> 6 <tr> 7 <td>密码</td> 8 <td><asp:TextBox ID="TextBox1" runat="server"></asp:TextBox></td> 9 </tr> 10 <tr> 11 <td colspan="2"><asp:Button ID="Button1" runat="server" Text="提 交" onclick="Button1_Click" /></td> 12 </tr> 13 </table>
后台
1 protected void Page_Load(object sender, EventArgs e) 2 { 3 if (!IsPostBack) 4 { 5 if (Request.Cookies[FormsAuthentication.FormsCookieName] != null) 6 Response.Redirect("Test1.aspx"); 7 } 8 } 9 10 protected void Button1_Click(object sender, EventArgs e) 11 { 12 FormsAuthentication.SetAuthCookie(txtName.Text, false); 13 }
创建一个测试页Test1.aspx
1 <form id="form1" runat="server"> 2 <div> 3 用户名: 4 <asp:Label runat="server" ID="lblUserName"></asp:Label> 5 已登录 6 7 <asp:Button runat="server" ID="btnLoginOut" Text="退 出" 8 onclick="btnLoginOut_Click" /> 9 </div> 10 </form>
后台
1 protected void Page_Load(object sender, EventArgs e) 2 { 3 if (!IsPostBack) 4 { 5 if (Request.Cookies[FormsAuthentication.FormsCookieName] == null) 6 Response.Redirect("Login.aspx"); 7 else 8 { 9 lblUserName.Text = Request.Cookies[FormsAuthentication.FormsCookieName].Name.ToString(); 10 } 11 } 12 } 13 14 protected void btnLoginOut_Click(object sender, EventArgs e) 15 { 16 FormsAuthentication.SignOut(); 17 }
我们直接运行Login.aspx进行登录,然后再运行Test1.aspx,显示结果如下:
用户名: LoginCookieName 已登录
LoginCookieName正是我们在Web.Config中配置的name的值吗。再利用firefox的自带工具查看一下本页的Cookie值
名称 LoginCookieName
值 E446C4B9D24D0F623023D6563D64C64AC082A41D685F28CEE9AE4CEEDFD0FFEE0D845EEADEC13FC81F33CA7E4E6B28291E95273A813C2D216C67
34E4D752D0F2CAA5F4B11ACA9FC355765810AFF2B0AFAACCD7AAFD04DD669C0CB52112EC277BC9347B1F
主机 localhost
路径 /
加密 否
到期 会话期间完即失效
结果确认Form认证模式,其实就是利用Cookie的机制实现的。
是否经过认证我们还可以下面的代码来判断
if (Request.IsAuthenticated)
{
Response.Redirect("Test1.aspx");
}
(四)同域下Cookie共享问题
有的时候往往会累到同域下共享Cookie的一系列问题,我总结一下基本出现的问题。
情况一:比如在主域登录后,在二级域中不作为一个已验证的用户,相反也是如此。
例如:主域名www.test.com,二级域名pass.test.com,如果我们在www.test.com中输入用户名/密码进行认证,认证成功后我们用代码FormsAuthentication.SetAuthCookie来设置Cookie,Cookie的域名往往被认为是www.test.com,我们再访问pass.test.com时,它的域名默认是pass.test.com,因为Cookie和domain(域名)是相关联的,如果在请求中域名不一致,Cookie将被忽略。因些,我们在设置Cookie时,请使用以下代码:
FormsAuthentication.SetAuthCookie(txtName.Text, false);
HttpCookie lcookie = Context.Response.Cookies[FormsAuthentication.FormsCookieName];
lcookie.Domain = ".test.com";
Response.Redirect(FormsAuthentication.GetRedirectUrl(txtName.Text, false));
情况二:主域和二级域不能同时注销问题
根据情况一的解释,我们同理可以推出,如何注销了吧,代码如下:
FormsAuthentication.SignOut();
HttpCookie lcookie2 = Context.Response.Cookies[FormsAuthentication.FormsCookieName];
lcookie2.Domain = ".test.com";
Response.Redirect("user.aspx");
(五) 自定义登录
上面可能一起我们在使用FormsAuthentication.SetAuthCookie来实现Form认证,其实我们还有另一种方式。代码如下
1 FormsAuthenticationTicket ticket = new FormsAuthenticationTicket( 2 2, "NewLog", DateTime.Now, DateTime.Now.Add(10d), false, string.Empty); 3 string str = FormsAuthentication.Encrypt(ticket); 4 5 6 HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, str); 7 Response.Cookies.Add(cookie);
其效果和FormsAuthentication.SetAuthCookie是一样的。这样写可能更灵活。
还可以自定义一些用户特定信息。这个我们将在下一章来讲。
转载的请注原创地址,谢谢。