現在 ASP.NET 2.0 提供了對成員資格(用戶名/密碼憑據存儲)和角色管理服務的內置支持。由於所有這些服務都是提供程序驅動的(Provider),因此可以方便地用您自己的自定義實現替換。
關鍵
1、基於Windows的身份驗證將<system.web>元素下的<authentication> 設置爲 Windows;基於Forms的身份驗證將<system.web>元素下的<authentication> 設置爲 Forms。
2、基於Forms的身份驗證時,設置<system.web>元素下的<authentication> 元素的 <forms> 子元素,示例如下,僅爲說明
<forms name=".VS2005_Form" loginUrl="~/Security/Login.aspx" defaultUrl="~/Default.aspx"
protection="All" timeout="30" path="/" requireSSL="false"
slidingExpiration="true" enableCrossAppRedirects="false"
cookieless="UseDeviceProfile">
</forms>
</authentication>
<forms>元素的屬性說明如下
1) cookieless - 身份驗證可以將 Forms 身份驗證票存儲在 Cookie 中也可以以無 Cookie 的表示形式存儲在 URL 上。有效值如下:
·UseDeviceProfile - 默認值表示 ASP.NET 根據預先計算得到的瀏覽器配置文件來確定存儲票證的位置。
·AutoDetect - 選項使 ASP.NET 動態確定瀏覽器是否支持 Cookie。
·UseUri - 強制實施無 Cookie 票證
·UseCookies - 強制實施有 Cookie 票證。
2) defaultUrl - 指定在成功登錄後,請求將重定向到的默認 URL。
3) domain - 指定包含 Forms 身份驗證票的 HttpCookie 的 Domain 屬性的值。顯式設置此屬性可使應用程序共享同一個 Cookie,前提是這些應用程序共享某個 DNS 命名空間的一個公共部分(例如,如果 domain 屬性設置爲“cnblogs.com”,則 webabcd.cnblogs.com 和 dudu.cnblogs.com可以共享一個 Cookie)。
4) enableCrossAppRedirects - Forms 身份驗證允許以查詢字符串變量或窗體 POST 變量的形式在應用程序之間傳遞 Forms身份驗證票。將此屬性設置爲 true 可使 FormsAuthenticationModule 能夠從查詢字符串或窗體 POST 變量提取票證。
5) loginUrl - 指定未經身份驗證的用戶的請求將被重定向到的 URL。該 URL 可以在同一臺計算機上或在遠程計算機上。如果是在遠程計算機上,則兩臺計算機上 machineKey 配置元素中的 decryptionkey 和 validationKey 屬性都需要使用相同的值。
6) name - 用於身份驗證的 HTTP Cookie 的名稱。注意,如果多個應用程序需要在一臺計算機上使用基於窗體的身份驗證服務,並且每個應用程序都希望由應用程序隔離 Forms 身份驗證 Cookie,則每個應用程序都應配置一個唯一的 Cookie 值。爲避免在 URL 中產生依賴項,在設置身份驗證 Cookie 時,ASP.NET 還使用“/”作爲 Path 值,以便將這些 Cookie 發送回站點上的每個應用程序。
7) path - 用於發出的 Cookie 的路徑。默認值爲“/”,以避免路徑中大小寫不匹配的造成的困難,因爲在返回 Cookie 時,瀏覽器是嚴格區分大小寫的。共享服務器環境中的應用程序應使用此指令來維護專用 Cookie。(它們還可以使用 API 在運行時指定路徑來發出 Cookie。)
8) protection - 用於保護 Cookie 數據的方法。有效值如下:
·All - 同時使用數據驗證和加密來保護 Cookie。所配置的數據驗證算法是基於 <machinekey> 元素的。如果密鑰足夠長(48 個字符),默認情況下將使用 AES 進行加密。All 是默認(和建議)值。
·None - 用於僅將 Cookie 用於個性化設置並且安全性要求不高的站點。加密和驗證都可以被禁用。儘管以此方式使用 Cookie 需謹慎,但對於使用 .NET Framework 實現個性化設置的任何方法,此設置提供了最佳性能。
·Encryption - 使用 AES、TripleDES 或 DES 加密 Cookie,但不對 Cookie 進行數據驗證。這類 Cookie 容易受到精心選擇的純文本的攻擊。
·Validation - 不加密 Cookie 的內容,但驗證 Cookie 數據在傳輸過程中是否未被更改。若要創建 Cookie,驗證密鑰在緩衝區中與 Cookie 數據連接,並且計算出 MAC 並將其追加到輸出的 Cookie。
9) requireSSL - 如果設置爲 true,則 Forms 身份驗證會設置 Forms 身份驗證 Cookie 的安全位。兼容的瀏覽器只將 Cookie 通過 SSL 連接發送回 ASP.NET。注意,如果使用無 Cookie Forms 身份驗證,則此設置無效。
10) slidingExpiration - 如果設置爲 true,則 Forms 身份驗證將定期更新 Forms 身份驗證票的生存期。無論票證是包含在 Cookie 中,還是以無 Cookie 的格式包含在 URL 中,都會進行此操作。
11) timeout - 時間量(以整數分鐘爲單位),經過該時間量之後,Cookie 則會過期。默認值是 30。超時屬性是一個可調值,從收到上次請求的時間開始計算,它將在 n 分鐘後過期。爲了避免對性能產生負面影響,也爲了避免那些打開了 Cookie 警告的應用程序產生多個瀏覽器警告,Cookie 在超時時間過半時更新。(這意味着在某些情況下可能會出現精度損失。) (注意:createPersistentCookie爲true的話,則該屬性失效,過期時間將爲50年)
3、授權用戶和角色設置<system.web>元素下的<authorization>元素,示例如下,僅爲說明
<allow VERB="POST" users="[email protected]" />
<allow roles="admin" />
<deny users="*" />
<allow VERB="GET" users="abc,xyz" />
<deny users="?" />
</authorization>
注:可以把授權用戶和角色設置的配置寫在某個文件夾內,則所做的配置只作用於該文件夾內,自動繼承外面的配置。
allow - 允許
deny - 拒絕
users - 用戶(多用戶用逗號隔開)
roles - 角色(多角色用逗號隔開)
verb - 指定http方法,post或get
* - 所有用戶
? - 匿名(未經過身份驗證的)用戶
4、分路徑設置授權用戶和角色設置,示例如下,僅爲說明
<system.web>
<authorization>
<deny users="?"/>
<allow users="*"/>
</authorization>
</system.web>
</location>
<location path="abc.aspx">
<system.web>
<authorization>
<allow roles="Administrators" />
<deny users="*"/>
</authorization>
</system.web>
</location>
<location>元素的path屬性可以是文件夾也可以是某一文件
5、<membership>元素設置,示例如下,僅爲說明
<providers>
<clear/>
<add name="SqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="SqlConnectionString"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
applicationName="/"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="3"
minRequiredPasswordLength="3"
minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10"
passwordStrengthRegularExpression="" />
</providers>
</membership>
enablePasswordRetrieval - 是否可以檢索用戶密碼(總是false)
enablePasswordReset - 是否允許用戶重置其密碼
requiresQuestionAndAnswer - 是否要求在創建用戶時提供密碼提示問題和答案
applicationName - 自定義成員資格提供程序的應用程序的名稱
requiresUniqueEmail - 電子郵件地址是否必須是唯一的
passwordFormat - 存儲的密碼的格式
maxInvalidPasswordAttempts - 指定允許的無效密碼或無效密碼提示問題答案嘗試的次數。當無效嘗試的次數達到配置的值時,將鎖定該成員資格用戶
minRequiredPasswordLength - 密碼所要求的最小長度
minRequiredNonalphanumericCharacters - 有效密碼中必須包含的最少特殊字符數
passwordAttemptWindow - 跟蹤失敗的嘗試所用的時間(以分鐘爲單位)。每當發生另一次失敗時都將重置窗口。如果達到了允許的無效密碼或密碼提示問題答案的最大嘗試次數,將鎖定成員資格用戶
passwordStrengthRegularExpression - 用於驗證密碼的正則表達式
6、<roleManager>元素設置,示例如下,僅爲說明
enabled="true"
cacheRolesInCookie="true"
cookieName=".VS2005_Role"
cookieTimeout="30"
cookiePath="/"
cookieRequireSSL="false"
cookieSlidingExpiration="true"
cookieProtection="All">
<providers>
<add
name="SqlRoleProvider"
type="System.Web.Security.SqlRoleProvider"
connectionStringName="SqlConnectionString"
applicationName="/" />
</providers>
</roleManager>
各屬性詳細說明參看MSDN,索引處查找“roleManager 元素”
7、使用加密密碼
<credentials passwordFormat="SHA1" >
<user name="Mary" password="94F85995C7492EEC546C321821AA4BECA9A3E2B1"/>
<user name="John" password="5753A498F025464D72E088A9D5D6E872592D5F91"/>
</credentials>
</authentication>
使用FormsAuthentication.HashPasswordForStoringInConfigFile(String password, String passwordFormat)生成密碼
Clear - 密碼以明文形式存儲
SHA1 - 密碼存儲爲 SHA1 摘要
MD5 - 密碼存儲爲 MD5 摘要
8、使用用戶帳戶模擬,在<system.web>元素下加如下元素
9、常用的就是如下這些東東
System.Web.Security.Membership,System.Web.Security.MembershipUser,System.Web.Security.Roles,Page.User
FormsAuthentication.RedirectFromLoginPage,FormsAuthentication.SetAuthCookie,FormsAuthentication.SignOut
重寫那些Provider的話,參看源碼中微軟提供的示例
示例
讀取用戶名和驗證類型
Security/Test.aspx
Inherits="Security_Test" Title="讀取用戶名和驗證類型" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<p>
用戶名稱:
<%=User.Identity.Name %>
<br />
驗證類型:
<%=User.Identity.AuthenticationType %>
</p>
</asp:Content>
Membership測試
App_Code/User.cs
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.ComponentModel;
/**//// <summary>
/// User 的摘要說明
/// </summary>
[DataObject(true)]
public class User
{
public User()
{
//
// TODO: 在此處添加構造函數邏輯
//
}
/**//// <summary>
/// 獲得所有用戶
/// </summary>
/// <returns></returns>
[DataObjectMethod(DataObjectMethodType.Select, true)]
public MembershipUserCollection GetMembers()
{
MembershipUserCollection muc = Membership.GetAllUsers();
return muc;
}
/**//// <summary>
/// 刪除用戶
/// </summary>
/// <returns></returns>
[DataObjectMethod(DataObjectMethodType.Delete, true)]
public void DeleteMember(string username)
{
Membership.DeleteUser(username, true);
}
}
Security/User.aspx
Inherits="Security_User" Title="Membership測試" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<p>
<asp:Label ID="lblMsg" runat="Server" ForeColor="red" />
</p>
<p>
用戶名:
<asp:TextBox ID="txtUsername" runat="server"></asp:TextBox>
</p>
<p>
密 碼:
<asp:TextBox ID="txtPassword" runat="server"></asp:TextBox>
</p>
<p>
<asp:Button ID="btnSubmit" runat="server" Text="添加" OnClick="btnSubmit_Click" />
</p>
<p>
<asp:GridView ID="GridView1" runat="server" DataKeyNames="UserName" AutoGenerateColumns="False"
DataSourceID="ObjectDataSource1">
<Columns>
<asp:CommandField ShowDeleteButton="True" />
<asp:BoundField DataField="ProviderName" HeaderText="ProviderName" ReadOnly="True"
SortExpression="ProviderName" />
<asp:CheckBoxField DataField="IsOnline" HeaderText="IsOnline" ReadOnly="True" SortExpression="IsOnline" />
<asp:BoundField DataField="LastPasswordChangedDate" HeaderText="LastPasswordChangedDate"
ReadOnly="True" SortExpression="LastPasswordChangedDate" />
<asp:BoundField DataField="PasswordQuestion" HeaderText="PasswordQuestion" ReadOnly="True"
SortExpression="PasswordQuestion" />
<asp:CheckBoxField DataField="IsLockedOut" HeaderText="IsLockedOut" ReadOnly="True"
SortExpression="IsLockedOut" />
<asp:BoundField DataField="Comment" HeaderText="Comment" SortExpression="Comment" />
<asp:BoundField DataField="UserName" HeaderText="UserName" ReadOnly="True" SortExpression="UserName" />
<asp:BoundField DataField="Email" HeaderText="Email" SortExpression="Email" />
<asp:BoundField DataField="CreationDate" HeaderText="CreationDate" ReadOnly="True"
SortExpression="CreationDate" />
<asp:CheckBoxField DataField="IsApproved" HeaderText="IsApproved" SortExpression="IsApproved" />
<asp:BoundField DataField="LastLockoutDate" HeaderText="LastLockoutDate" ReadOnly="True"
SortExpression="LastLockoutDate" />
<asp:BoundField DataField="LastLoginDate" HeaderText="LastLoginDate" SortExpression="LastLoginDate" />
<asp:BoundField DataField="LastActivityDate" HeaderText="LastActivityDate" SortExpression="LastActivityDate" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="GetMembers"
TypeName="User" DeleteMethod="DeleteMember">
<DeleteParameters>
<asp:Parameter Name="username" Type="String" />
</DeleteParameters>
</asp:ObjectDataSource>
</p>
<p>
備註:<br />
用戶和角色之間的操作如下<br />
Roles.AddUserToRole - 向角色添加用戶<br />
Roles.RemoveUserFromRole - 從角色刪除用戶<br />
Roles.GetRolesForUser - 用戶所屬的角色列表<br />
</p>
</asp:Content>
Security/User.aspx.cs
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class Security_User : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
MembershipCreateStatus status;
Membership.CreateUser(txtUsername.Text.Trim(), txtPassword.Text.Trim(), null, null, null, true, out status);
string strInsertMessage = "";
switch (status)
{
case MembershipCreateStatus.Success:
break;
case MembershipCreateStatus.DuplicateUserName:
strInsertMessage = "用戶名重複";
break;
case MembershipCreateStatus.InvalidUserName:
strInsertMessage = "用戶名輸入錯誤";
break;
case MembershipCreateStatus.InvalidPassword:
strInsertMessage = "密碼輸入不符合要求";
break;
default:
strInsertMessage = "出現未知錯誤";
break;
}
if (strInsertMessage != "")
{
lblMsg.Text = strInsertMessage;
}
else
{
lblMsg.Text = "註冊成功";
GridView1.DataBind();
}
}
}
RoleManager測試
App_Code/Role.cs
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections.Generic;
using System.ComponentModel;
/**//// <summary>
/// Role 的摘要說明
/// </summary>
[DataObject(true)]
public class Role
{
public Role()
{
//
// TODO: 在此處添加構造函數邏輯
//
}
/**//// <summary>
/// 得到所有角色
/// </summary>
/// <param name="userName">用戶名稱</param>
/// <returns></returns>
[DataObjectMethod(DataObjectMethodType.Select, true)]
static public List<RoleData> GetRoles()
{
RoleData r = null;
List<RoleData> roleList = new List<RoleData>();
string[] ary = Roles.GetAllRoles();
foreach (string s in ary)
{
r = new RoleData();
r.RoleName = s;
roleList.Add(r);
}
return roleList;
}
/**//// <summary>
/// 刪除角色
/// </summary>
/// <param name="roleName">角色名稱</param>
[DataObjectMethod(DataObjectMethodType.Delete, true)]
static public void DeleteRole(string roleName)
{
MembershipUserCollection muc = Membership.GetAllUsers();
string[] allUserNames = new string[1];
foreach (MembershipUser mu in muc)
{
if (Roles.IsUserInRole(mu.UserName, roleName))
{
allUserNames[0] = mu.UserName;
Roles.RemoveUsersFromRole(allUserNames, roleName);
}
}
Roles.DeleteRole(roleName);
}
}
/**//// <summary>
/// 角色的實體類
/// </summary>
public class RoleData
{
protected string _roleName;
/**//// <summary>
/// 角色名稱 關鍵字
/// </summary>
[DataObjectField(true)]
public string RoleName
{
get { return this._roleName; }
set { this._roleName = value; }
}
}
Security/Role.aspx
Inherits="Security_Role" Title="RoleManager測試" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<p>
<asp:Label ID="lblMsg" runat="Server" ForeColor="red" />
</p>
<p>
角色名:
<asp:TextBox ID="txtRolename" runat="server"></asp:TextBox>
</p>
<p>
<asp:Button ID="btnSubmit" runat="server" Text="添加" OnClick="btnSubmit_Click" />
</p>
<p>
<asp:GridView ID="GridView1" runat="server" DataKeyNames="RoleName" DataSourceID="ObjectDataSource1" AutoGenerateColumns="False">
<Columns>
<asp:CommandField ShowDeleteButton="True" />
<asp:BoundField DataField="RoleName" HeaderText="RoleName" ReadOnly="True"
SortExpression="RoleName" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" DeleteMethod="DeleteRole"
SelectMethod="GetRoles" TypeName="Role">
<DeleteParameters>
<asp:Parameter Name="roleName" Type="String" />
</DeleteParameters>
</asp:ObjectDataSource>
</p>
<p>
備註:<br />
用戶和角色之間的操作如下<br />
Roles.AddUserToRole - 向角色添加用戶<br />
Roles.RemoveUserFromRole - 從角色刪除用戶<br />
Roles.GetRolesForUser - 用戶所屬的角色列表<br />
</p>
</asp:Content>
Security/Role.aspx.cs
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class Security_Role : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
if (Roles.RoleExists(txtRolename.Text.Trim()))
{
lblMsg.Text = "該角色已存在";
}
else
{
Roles.CreateRole(txtRolename.Text.Trim());
GridView1.DataBind();
}
}
}
注:需要用aspnet_regsql配置數據庫