【原创】Cookie应用(二)

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是一样的。这样写可能更灵活。
还可以自定义一些用户特定信息。这个我们将在下一章来讲。

 转载的请注原创地址,谢谢。

原文地址:https://www.cnblogs.com/yxhblog/p/2553828.html