Membership学习(三)Membership Providers介绍[xgluxv]
本來想在第三篇文章里介紹一下 Membership的類的,不過現在中文msdn也出來了,所以就不寫了,,直接到介紹Membership Providers。
?????? Membership Providers提供了Membership數據源和服務之間的所有接口,在Asp.net2.0中提供了兩個Provider:SqlMembershipProvider和ActiveDirectoryMembershipProvider,從命名中我們也可以看出,SqlMembershipProvider是把 sql server和sql server express數據庫作為數據庫源,而ActiveDirectoryMembershipProvider是有Microsoft Active Directory(活動目錄)作為數據源的。
??????? Membership Providers的基本工作是用來管理一個網站注冊用的數據,并且提供一些函數用來做 創建,刪除用戶,驗證用戶登錄信息,修改密碼等工作。在.net 框架的System.Web.Security命名空間下有一個MembershipUser的類,這個類定義了Membership 用戶的一些基本屬性,Membership Provider用這個類來描繪每個用戶信息。Membership Providers 有一個基礎類 他的定義如下:(叢msdn里copy出來的)
?
public?abstract?class?MembershipProvider?:?ProviderBase{
????//?Abstract?properties
????public?abstract?bool?EnablePasswordRetrieval?{?get;?}
????public?abstract?bool?EnablePasswordReset?{?get;?}
????public?abstract?bool?RequiresQuestionAndAnswer?{?get;?}
????public?abstract?string?ApplicationName?{?get;?set;?}
????public?abstract?int?MaxInvalidPasswordAttempts?{?get;?}
????public?abstract?int?PasswordAttemptWindow?{?get;?}
????public?abstract?bool?RequiresUniqueEmail?{?get;?}
????public?abstract?MembershipPasswordFormat?PasswordFormat?{?get;?}
????public?abstract?int?MinRequiredPasswordLength?{?get;?}
????public?abstract?int?MinRequiredNonAlphanumericCharacters?{?get;?}
????public?abstract?string?PasswordStrengthRegularExpression?{?get;?}
????//?Abstract?methods
????public?abstract?MembershipUser?CreateUser?(string?username,?
????????string?password,?string?email,?string?passwordQuestion,?
????????string?passwordAnswer,?bool?isApproved,?object?providerUserKey,
????????out?MembershipCreateStatus?status);
????public?abstract?bool?ChangePasswordQuestionAndAnswer
????????(string?username,?string?password,
????????string?newPasswordQuestion,?string?newPasswordAnswer);
????public?abstract?string?GetPassword?(string?username,
??????string?answer);
????public?abstract?bool?ChangePassword?(string?username,
????????string?oldPassword,?string?newPassword);
????public?abstract?string?ResetPassword?(string?username,
????????string?answer);
?
????public?abstract?void?UpdateUser?(MembershipUser?user);
????public?abstract?bool?ValidateUser?(string?username,
????????string?password);
????public?abstract?bool?UnlockUser?(string?userName);
????public?abstract?MembershipUser?GetUser?(object?providerUserKey,
????????bool?userIsOnline);
????public?abstract?MembershipUser?GetUser?(string?username,
????????bool?userIsOnline);
????public?abstract?string?GetUserNameByEmail?(string?email);
????public?abstract?bool?DeleteUser?(string?username,
????????bool?deleteAllRelatedData);
????public?abstract?MembershipUserCollection?GetAllUsers
????????(int?pageIndex,?int?pageSize,?out?int?totalRecords);
????public?abstract?int?GetNumberOfUsersOnline?();
????public?abstract?MembershipUserCollection?FindUsersByName
????????(string?usernameToMatch,?int?pageIndex,?int?pageSize,
????????out?int?totalRecords);
????public?abstract?MembershipUserCollection?FindUsersByEmail
????????(string?emailToMatch,?int?pageIndex,?int?pageSize,
????????out?int?totalRecords);
????//?Virtual?methods
????protected?virtual?byte[]?EncryptPassword?(byte[]?password);
????protected?virtual?byte[]?DecryptPassword?(byte[]?encodedPassword);
????protected?virtual?void?OnValidatingPassword
????????(ValidatePasswordEventArgs?e);
????//?Events
????public?event?MembershipValidatePasswordEventHandler
????????ValidatingPassword;
}
?
SqlMembershipProvider類就是從這個類里繼承下來的。
接下來 我們使用SqlMembershipProvider類作為例子來進行比較細致的說明。
SqlMembershipProvider:
SqlMembershipProvider是給Membership使用sql server數據庫做的Provider,它使用數據庫的存儲過程來實現對數據的操作,這樣SqlMembershipProvider可以經過很少的改動來 實現對其他數據庫的支持。
1.Provider 初始化
??? Provider初始化是在 SqlMembershipProvider.Initialize,它只運行一次,是在asp.net裝載Provider時。
??? a.初始化SqlMembershipProvider的各種屬性 比如:EnablePasswordRetrieval 和 EnablePasswordReset,從相應的配置文件的配置屬性中讀入。
??? b.對一些公共屬性的值進行檢查,當有錯誤的時候拋出異常,比如PasswordFormat值是”hashed”,而EnablePasswordRetrieval的值是true,就會有異常拋出。
?? c.在配置里存在一些不被承認的屬性時,也會拋出異常
??? SqlMembershipProvider.Initialize還會從<connectionStrings>中讀取數據庫連接字符串,保存到一個私有的變量中,如果不能讀到或者讀取的連接字符串是錯誤的,也會拋出一個異常。
2.數據定義
??? SqlMembershipProvider的Membership數據保存在數據庫的aspnet_Membership表中
aspnet_Membership 定義(msdn中取出)
| 字段名 | 字段類型 | 表述 |
| ApplicationId | uniqueidentifier | Application ID,應用程序id |
| UserId | uniqueidentifier | User ID,用戶id |
| Password | nvarchar(128) | 密碼,可以是加密 hash保存的 |
| PasswordFormat | int | Password format (0=Plaintext, 1=Hashed, 2=Encrypted) |
| PasswordSalt | nvarchar(128) | Randomly generated 128-bit value used to salt password hashes; stored in base-64-encoded form |
| MobilePIN | nvarchar(16) | User's mobile PIN (當前沒有使用) |
| | nvarchar(256) | |
| LoweredEmail | nvarchar(256) | 小寫email地址 |
| PasswordQuestion | nvarchar(256) | 密碼問題 |
| PasswordAnswer | nvarchar(128) | 密碼問題答案 |
| IsApproved | bit | 1=Approved, 0=Not approved |
| IsLockedOut | bit | 1=Locked out, 0=Not locked out |
| CreateDate | datetime | 創建時間 |
| LastLoginDate | datetime | 最后登錄時間 |
| LastPasswordChangedDate | datetime | 密碼最后修改時間 |
| LastLockoutDate | datetime | 最后登出的時間 |
| FailedPasswordAttemptCount | int | 聯系登錄失敗次數 |
| FailedPasswordAttempt-WindowStart | datetime | ?在FailedPasswordAttemptCount非零時,第一次登錄失敗的時間 ? |
| FailedPasswordAnswer-AttemptCount | int | 回答密碼問題聯系失敗的次數 |
| FailedPasswordAnswer-AttemptWindowStart | datetime | 在FailedPasswordAnswer-AttemptCount非零時,第一次回答問題失敗的時間 |
| Comment | ntext | 擴展的文本 |
?
這個表中的每一條記錄代表一個用戶,這個表還有兩個外鍵,分別關聯aspnet_Applications表和aspnet_Users表
?aspnet_Applications表
| 字段名 | 字段類型 | 描述 |
| ApplicationId | uniqueidentifier | Application ID |
| ApplicationName | nvarchar(256) | Application name |
| LoweredApplicationName | nvarchar(256) | Application name (小寫) |
| Description | nvarchar(256) | Application 描述 |
?aspnet_Users 表
| 字段名 | 字段類型 | 描述 |
| ApplicationId | uniqueidentifier | Application ID |
| UserId | uniqueidentifier | 用戶ID |
| UserName | nvarchar(256) | 用戶名 |
| LoweredUserName | nvarchar(256) | 用戶名 (小寫) |
| MobileAlias | nvarchar(16) | User's mobile alias (currently not used) 沒有使用 |
| IsAnonymous | bit | 1=Anonymous user, 0=Not an anonymous user |
| LastActivityDate | datetime | 用戶最后一次活動時間 |
?一條完整的記錄 aspnet_Membership和aspnet_Users都要存在。
3.數據訪問
SqlMembershipProvider是通過存儲過程完成所有的數據庫操作的,簡單介紹一下這些存儲過程
SqlMembershipProvider存儲過程
| 名稱 | 描述 |
| aspnet_Membership_ChangePassword-QuestionAndAnswer | 修改密碼,密碼問題,密碼問題答案 |
| aspnet_Membership_CreateUser | 增加一個membership用戶 記錄同時寫入aspnet_Users 和aspnet_Membership 表, 如果需要,還要增加一條記錄到aspnet_Applications表。 |
| aspnet_Membership_FindUsersByEmail | 通過email地址匹配查找用戶的記錄,同時還要一個application ID. |
| aspnet_Membership_FindUsersByName | 通過用戶名匹配查找用戶的記錄,同時還要一個application ID. |
| aspnet_Membership_GetAllUsers | 得到所有用戶記錄,在一個下application ID. |
| aspnet_Membership_GetNumberOfUsersOnline | 得到在線用戶數 (通過用戶最后活動時間字段(LastActivityDate)實現) |
| aspnet_Membership_GetPassword | 得到一個用戶的密碼,通過密碼問題的回答 |
| aspnet_Membership_GetPasswordWithFormat | 得到一個用戶的密碼。通過密碼比較重新取得密碼。 |
| aspnet_Membership_GetUserByEmail | 使用email和application id從aspnet_Membership中得到相應的記錄 |
| aspnet_Membership_GetUserByName | 使用用戶名和application id從aspnet_Membership中得到相應的記錄 |
| aspnet_Membership_GetUserByUserId | 使用userid和application id從aspnet_Membership中得到相應的記錄 |
| aspnet_Membership_ResetPassword | 重置用戶密碼通過回答密碼問題 |
| aspnet_Membership_SetPassword | 設置一個密碼 |
| aspnet_Membership_UnlockUser | 恢復用戶登錄的權限通過將IsLockedOut字段設置成0 |
| aspnet_Membership_UpdateUser | 更新用戶的aspnet_users表的LastActivityDate,e-mail,注釋,approved字段和aspnet_Membership表的最后登錄時間。 |
| aspnet_Membership_UpdateUserInfo | 更新帳戶鎖定時間在aspnet_users和aspnet_Membership表,Used in conjunction with provider methods that track bad password and bad password-answer attempts. ? |
| aspnet_Users_CreateUser | 調用aspnet_Membership_CreateUser增加一個到用戶到aspnet_users表。 ? |
| aspnet_Users_DeleteUser | 刪除一個用戶 從aspnet_membership已經一些關聯表里包括aspnet_users. |
?
4.創建用戶
SqlMembershipProvider.CreateUser通過調用aspnet_Membership_CreateUser儲存過程創建membership用戶。SqlMembershipProvider.CreateUser在調用存儲過程之前還會對用戶的輸入參數做一些校驗,包括密碼等。
創建用戶的流程
a.?????????????? 調用aspnet_Applications_CreateApplication,存儲過程,轉換一個ApplicationName成Application ID.如果在aspnet_Applications表中已經存在這個Application ID就返回存在Application ID,如果表中不存在,在aspnet_Applications表中新增加一條記錄并返回這個Application ID.
b.?????????????? 調用aspnet_Users_CreateUser在aspnet_Users表中添加一條新記錄
c.?????????????? 做一個驗證對email地址和原來已經注冊的用戶。
d.?????????????? 使用當前的時間來更新一下aspnet_Users表的LastActityDate字段。
e.?????????????? 插入一條新記錄到aspnet_Membership表。
aspnet_Membership_CreateUser提供了所有的這些步驟,并使用事務來保證數據庫更新的完整性。
?
5.刪除用戶
程序通過調用Membership.DeleteUser來實現刪除membership用戶的功能。
Membership.DeleteUser調用默認的membership提供者的DeleteUser的函數,而這個函數有兩個輸入值,一個是用戶名 另外一個參數(deleteAllRelatedData)是bool值,這個bool值表示是否要刪除這個用戶的一些關聯信息,包括role data, profile data和 Web Parts personalization data。
DeleteUser還可以實現一個其他的功能就是 把用戶名輸入Request.AnonymousID,而參數deleteAllRelatedData設置為true,這樣可以刪除匿名用戶在數據庫的aspnet_Profile和aspnet_Users表中保存的記錄。
6.驗證membership用戶
程序通用調用Membership.ValidateUser來實現用戶的驗證,返回值是一個bool值,包括用戶名密碼是否正確。
驗證的流程
a.????????????? 通過調用存儲過程 aspnet_Membership_GetPasswordWithFormat得到用戶的密碼,如果是加密的返回的是加密的字串。
b.????????????? 使用相同的加密碼方法加密輸入的密碼。
c.????????????? 比較兩個密碼。
d.????????????? 如果密碼匹配 會觸發一個AuditMembershipAuthenticationSuccess的Web 事件,同時記錄一個成功登陸的紀錄,并返回true
e.????????????? 如果密碼不匹配,會觸發一個 AuditMembershipAuthenticationFailure的web 事件,返回false,同時還會調用aspnet_Membership_UpdateUserInfo儲存過程做記錄,如果記錄發現已經達到限制用戶登錄的條件,還會鎖住此用戶。
7.密碼保護
為了安全,密碼保存在數據庫中一般不用明文,SqlMembershipProvider提供了幾種不同保存密碼的方法,我們可以通過設置PasswordFormat屬性來指定不同的保存方法。
a.??? MembershipPasswordFormat.Clear使用明文保存
b.??? MembershipPasswordFormat.Hashed 默認參數,會使用.Net框架的RNGCryptoServiceProvider類來對密碼和密碼問題進行Hash計算保存。
c.??? MembershipPasswordFormat.Encrypted對密碼和密碼問題進行加密。SqlMembershipProvider使用的是對稱密鑰加密方法。加密的密鑰保存在<machineKey>配置字段里
為了增加一些額外的安全保護,SqlMembershipProvider還提供了MinRequiredPasswordLength,MinRequiredNonAlphanumericCharacters,PasswordStrengthRegularExpression三個屬性來加強保護,根據字面意思應該是密碼最小長度,最少特殊字符數,密碼正則表達式。
8.帳戶鎖定
為了抵御窮舉密碼 猜密碼的攻擊,SqlMembershipProvider提供了一個自動鎖定用戶的機制,當一個帳戶在一段時間內連續登錄失敗超過一定次數后,這個用戶將被鎖定,SqlMembershipProvider的MaxInvalidPasswordAttempts和PasswordAttemptWindow屬性,默認MaxInvalidPasswordAttempts=5次,PasswordAttemptWindow=10分鐘。當數據表里的IsLockedOut=1時用戶就被鎖定了。
對Membership Provider等Provider微軟提供了源代碼,但這些源代碼和.Net框架里包含的是有區別的,主要是為了能讓提供的源代碼能讓用戶獨立的編譯和運行。
今天這篇文章寫的太長,自己都有點暈了,有錯誤的地方多包涵。
轉載于:https://www.cnblogs.com/dotLive/archive/2006/07/27/461243.html
總結
以上是生活随笔為你收集整理的Membership学习(三)Membership Providers介绍[xgluxv]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu 1251 统计难题(求前缀出现了
- 下一篇: Mysql远程登录及常用命令