閱讀227 返回首頁    go 阿裏雲 go 技術社區[雲棲]


[.NET 基於角色安全性驗證] 之三:ASP.NET Forms 身份驗證

在開發過程中,我們需要做的事情包括:

1. 在 web.config 中設置 Forms 身份驗證相關參數。
2. 創建登錄頁。

登錄頁中的操作包括:

1. 驗證用戶名和密碼是否正確。
2. 創建身份驗證票證對象。
3. 將身份驗證票證對象加密成字符串,寫入 Cookies。
4. 重定向到原始請求 URL。

1. 簡單演示

web.config
<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true"/>
    <authentication mode="Forms">
      <forms loginUrl="~/logon.aspx" name="MyAuthForm">
        <credentials passwordFormat="Clear">
          <user name="username" password="password"/>
        </credentials>
      </forms>
    </authentication>
    <authorization>
      <deny users="?"/>
    </authorization>
  </system.web>
</configuration>

logon.aspx
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
  protected void Button1_Click(object sender, EventArgs e)
  {
    if (FormsAuthentication.Authenticate(this.txtUsername.Text, this.txtPassword.Text))
      FormsAuthentication.RedirectFromLoginPage(this.txtUsername.Text, true);
    else
      Response.Write("用戶名或密碼錯誤!");
  }
</script>

<html xmlns="https://www.w3.org/1999/xhtml" >
<head runat="server">
 <title>登錄頁</title>
</head>
<body>
 <form runat="server">
 <div>
    Username: <asp:TextBox ID="txtUsername" runat="server" Width="100px" Text="username"></asp:TextBox><br />
    Password: <asp:TextBox ID="txtPassword" runat="server" Width="100px" Text="password"></asp:TextBox><br />
    <asp:Button ID="Button1" runat="server" Text="Sign In" OnClick="Button1_Click" />
 </div>
 </form>
</body>
</html>

2. Forms 驗證參數

如果隻是某些子目錄中的頁麵訪問請求需要進行身份驗證,那麼可以修改一下根路徑下的 web.config。

web.config
<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true"/>
    <authentication mode="Forms">
      <forms loginUrl="~/logon.aspx" name="MyAuthForm">
        <credentials passwordFormat="Clear">
          <user name="username" password="password"/>
        </credentials>
      </forms>
    </authentication>
    <authorization>
      <allow users="*"/>
    </authorization>
  </system.web>
</configuration>

然後在需要進行身份驗證的子目錄中創建一個新的 web.config。
<?xml version="1.0"?>
<configuration>
  <system.web>
    <authorization>
      <deny users="?"/>
    </authorization>
  </system.web>
</configuration>

我們還可以在根路徑下的 web.config 中指定相關參數來控製身份驗證模式。
cookieless
  定義是否使用 Cookie 以及 Cookie 的行為。
  .UseCookies
    指定無論在什麼設備上都始終使用 Cookie。
  .UseUri
    指定從不使用 Cookie。
  .AutoDetect
    如果設備配置文件支持 Cookie,則指定使用 Cookie;否則不使用 Cookie。
  .UseDeviceProfile
    如果瀏覽器支持 Cookie,則指定使用 Cookie;否則不使用 Cookie。
    對於支持 Cookie 的設備,不嚐試通過探測來確定是否已啟用 Cookie 支持。
 
defaultUrl
  定義在身份驗證之後用於重定向的默認 URL。 默認值為 "default.aspx"。
  當我們直接打開登錄頁進行登錄後,該屬性就很重要了。

loginUrl
  指定如果找不到任何有效的身份驗證 Cookie,將請求重定向到的用於登錄的 URL。默認值為 login.aspx。
 
name
  指定要用於身份驗證的 HTTP Cookie。如果正在一台服務器上運行多個應用程序並且每個應用程序都需要
  唯一的 Cookie,則必須在每個應用程序的 Web.config 文件中配置 Cookie 名稱。默認值為 ".ASPXAUTH"。
 
path
  為應用程序發出的 Cookie 指定路徑。
  默認值是斜杠 (/),這是因為大多數瀏覽器是區分大小寫的,如果路徑大小寫不匹配,瀏覽器不會送回 Cookie。
 
timeout
  指定 Cookie 過期前逝去的時間(以整數分鍾為單位)。持久性 Cookie 不超時。默認值為 "30"(30 分鍾)。

更詳細信息,請參考 MSDN 文檔。
ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.NETDEVFX.v20.chs/dv_ASPNETgenref/html/8163b8b5-ea6c-46c8-b5a9-c4c3de31c0b3.htm
<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true"/>
    <authentication mode="Forms">
      <forms loginUrl="~/logon.aspx" name="MyForm" defaultUrl="index.aspx" timeout="10">
        <credentials passwordFormat="Clear">
          <user name="username" password="password"/>
        </credentials>
      </forms>
    </authentication>
    <authorization>
      <allow users="*"/>
    </authorization>
  </system.web>
</configuration>

3. 驗證方法

我們可以使用下麵 4 種方法中的一種進行票證寫入和重定向操作,其實前 3 種隻不過是對第 4 種方法的封裝而已。推薦使用 1、4。注意後三種方法不支持cookieless="UseUri"。
// 1. 使用缺省身份驗證票證
FormsAuthentication.RedirectFromLoginPage("username", true);

// 2. 使用缺省身份驗證票證
FormsAuthentication.SetAuthCookie("username", false);
Response.Redirect(FormsAuthentication.GetRedirectUrl("username", false));

// 3. 使用缺省身份驗證票證
Response.Cookies.Add(FormsAuthentication.GetAuthCookie("username", false));
Response.Redirect(FormsAuthentication.GetRedirectUrl("username", false));

// 4. 使用自定義身份驗證票證
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, "username", DateTime.Now, DateTime.Now.AddMinutes(10), false, null);
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(ticket)));
Response.Redirect(FormsAuthentication.GetRedirectUrl("username", false));

4. 自定義身份標識類型

MSDN 文檔告訴我們,可以在 Global.asax 中通過 Authenticate 事件使用自定義 Principal、Identity 替代 GenericPrincipal、FormsIdentity。因為 Authenticate 事件在 AuthenticateRequest 事件期間引發,因此我們可以在其他模塊之前創建用戶身份標識對象(FormsAuthenticationEventArgs.User)。

ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.NETDEVFX.v20.chs/cpref12/html/T_System_Web_Security_FormsAuthenticationEventHandler.htm
class MyPrincipal : System.Security.Principal.IPrincipal
{
  // ...
}

class MyIdentity : System.Security.Principal.IIdentity
{
  // ...
}
  
public void FormsAuthentication_OnAuthenticate(object sender, FormsAuthenticationEventArgs args)
{
  if (FormsAuthentication.CookiesSupported)
  {
    if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
    {
      try
      {
        FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(
          Request.Cookies[FormsAuthentication.FormsCookieName].Value);
 
        args.User = new MyPrincipal(new MyIdentity (ticket), new string[0]);
      }
      catch (Exception e)
      {
        // Decrypt method failed.
      }
    }
  }
  else
  {
    throw new HttpException("Cookieless Forms Authentication is not " +
      "supported for this application.");
  }

}

當然,還有另外一種簡便的方法。
if (!(HttpContext.Current.User is MyPrincipal))
{
  HttpContext.Current.User = new MyPrincipal(new MyIdentity(ticket), roles);
}

隻不過,你要找一個合適的時機而已。

5. FormsAuthentication

Authenticate
對照存儲在應用程序配置文件中的憑據來驗證用戶名和密碼。該方法隻能驗證存儲在 web.config 中的用戶名和密碼信息,大多數時候我們會用自己的驗證方法替代它。

Decrypt
解密從 Cookie 中獲取的加密字符串,創建 FormsAuthenticationTicket 對象。

Encrypt
加密 FormsAuthenticationTicket,返回加密後字符串。

GetRedirectUrl
返回導致重定向到登錄頁的原始請求 URL。GetRedirectUrl 方法返回查詢字符串中使用 ReturnURL 變量名指定的 URL。例如,在 URL https://www.contoso.com/login.aspx?ReturnUrl=caller.aspx 中,GetRedirectUrl 方法返回返回 caller.aspx。如果 ReturnURL 變量不存在,GetRedirectUrl 方法將返回 DefaultUrl 屬性中的 URL。

RedirectFromLoginPage
將經過身份驗證的用戶重定向回最初請求的 URL 或 DefaultUrl 。

RedirectToLoginPage
將瀏覽器重定向到登錄 URL。

RenewTicketIfOld
有條件地更新 FormsAuthenticationTicket 的發出日期和時間以及過期日期和時間。 注意該方法隻是返回更新後的 FormsAuthenticationTicket 對象,並不會寫入 Cookies。

GetAuthCookie
為給定的用戶名創建身份驗證 Cookie,並不添加到響應的 Cookie 集合或 URL。

SetAuthCookie
為提供的用戶名創建一個身份驗證票證,並將其添加到響應的 Cookie 集合或 URL。

SignOut
從瀏覽器刪除 Forms 身份驗證票證。

6. 票證自定義數據應用

使用自定義票證時,我們可以添加一個 userData 參數。善加利用這個參數還是能帶了一些意想不到的好處的,諸如存儲用戶 VIP 等級編號,所擁有的權限/角色集合等。當然 Cookie 和 URL 參數長度有限,這個自定義數據不能太長。  

最後更新:2017-04-02 00:06:27

  上一篇:go 四層體係結構介紹
  下一篇:go [.NET 基於角色安全性驗證] 之一:基礎知識