ASP.NETWhidbey中實現Provider
|
“Whidbey”是微軟工具套件的下一個版本。按照微軟的計劃,它將會在2004年底推出。
Asp.Net 2.0(codename Whidbey)通過Provider模式為用戶驗證、角色管理等方面提供了非常強大易用的框架模型。Whidbey中提供了一個Asp.Net configuration工具,通過它可以非常容易地配置用戶信息數據庫,管理角色等等,再與新加入的Security控件配合,幾乎不用寫什么代碼就能夠實現用戶驗證和角色管理功能。關于這些控件和配置工具的具體使用,可以參考這篇文章:使用更精簡的代碼保證 ASP.NET 應用程序的安全
但是在PDC Preview版本的Whidbey中,這個配置工具的功能還不是很完善。從我使用的情況來看,它目前還只能創建和連接自己的Demo用的Access數據庫,不能連接SQL Server數據庫進行擴展。因此,為了能夠連接SQL Server,我們必須提供我們自己的Providers。這里以連接IBuySpy的Portal數據庫為例來說明如何實現一個Membership Provider。
為了搞清楚如何實現我們自己的Membership Provider,有必要先看看Whidbey默認使用的Membership Provider是如何做的。在machine.config配置文件中,Whidbey使用類似下面這樣的配置實現:
<membership defaultProvider="AspNetAccessProvider" userIsOnlineTimeWindow="15" > <providers> <add name="AspNetSqlProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=1.2.3400.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="LocalSqlServer" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" applicationName="/" requiresUniqueEmail="false" passwordFormat="Hashed" description="Stores and retrieves membership data from the local Microsoft SQL Server database" /> <add name="AspNetAccessProvider" type="System.Web.Security.AccessMembershipProvider, System.Web, Version=1.2.3400.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="AccessFileName" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" applicationName="/" requiresUniqueEmail="false" passwordFormat="Hashed" description="Stores and retrieves membership data from the local Microsoft Access database file" /> </providers> </membership> |
關于這段配置文件的更詳細解說,可以參考《A First Look at ASP.NET v. 2.0》。
可以看出,Whidbey默認使用SqlMembershipProvider或者AccessMembershipProvider來進行用戶驗證和管理。這兩個Provider實現了IProvider和IMembershipProvider接口,實際上這兩個接口也是每個MembershipProvider所必需的,其中IProvider負責Provider的初始化,而IMembershipProvider則實現MembershipProvider的主要功能。它們的定義如下:
namespace System.Configuration.Provider { public interface IProvider { public string Name { get; } public void Initialize(string name, System.Collections.Specialized.NameValueCollection config); } } namespace System.Web.Security { public interface IMembershipProvider { public bool ChangePassword(string name, string oldPwd, string newPwd); public bool ChangePasswordQuestionAndAnswer(string name, string password, string newPwdQuestion, string newPwdAnswer); public System.Web.Security.MembershipUser CreateUser(string username, string password, string email,out System.Web.Security.MembershipCreateStatus status); public bool DeleteUser(string name); public System.Web.Security.MembershipUserCollection GetAllUsers(); public int GetNumberOfUsersOnline(); public string GetPassword(string name, string answer); public System.Web.Security.MembershipUser GetUser(string name,bool userIsOnline); public string GetUserNameByEmail(string email); public string ResetPassword(string name, string answer); public void UpdateUser(System.Web.Security.MembershipUser user); public bool ValidateUser(string name, string password); public string ApplicationName {get; set;} public bool EnablePasswordReset { get;} public bool EnablePasswordRetrieval { get;} public bool RequiresQuestionAndAnswer { get;} } } |
現在可以動手來實現我們自己的MembershipProvider了:
public class MyMembershipProvider : IProvider, IMembershipProvider { …… } |
驗證功能是必需的:
public bool ValidateUser (string name, string password) { string connectStr = ConfigurationSettings.ConnectionStrings["PortalData"]; SqlConnection myConnection = new SqlConnection (connectStr); SqlCommand myCommand = new SqlCommand ("UserLogin", myConnection); myCommand.CommandType = CommandType.StoredProcedure; // Add Parameters to SPROC SqlParameter parameterEmail = new SqlParameter ("@Email", SqlDbType.NVarChar, 100); parameterEmail.Value = name; myCommand.Parameters.Add (parameterEmail); SqlParameter parameterPassword = new SqlParameter ("@Password", SqlDbType.NVarChar, 20); parameterPassword.Value = password; myCommand.Parameters.Add (parameterPassword); SqlParameter parameterUserName = new SqlParameter ("@UserName", SqlDbType.NVarChar, 100); parameterUserName.Direction = ParameterDirection.Output; myCommand.Parameters.Add (parameterUserName); // Open the database connection and execute the command myConnection.Open (); myCommand.ExecuteNonQuery (); myConnection.Close (); if ((parameterUserName.Value != null) && (parameterUserName.Value != System.DBNull.Value)) return true; return false; } |
現在在web.config中可以這樣配置connectionString了:
<connectionStrings> <add name="BugDepotData" connectionString="Data Source=(local);Trusted_Connection=true;Database=Portal" /> </connectionStrings> |
這樣,我們自己的一個簡單的MembershipProvider就基本上完成了。接下來需要配置web.config,讓需要Provider服務的控件能夠認識它:
<membership> <providers> <add name="MyMembershipProvider" type="MyMembershipProvider" appName="/" /> </providers> </membership> |
這段設置是參考machine.config而來的,其中type屬性的值是這樣的字符串:
type="ProviderType, Assembly, Version, Culture, PublicKeyToken" |
由于我們的MyMembershipProvider放在/Code目錄下,并不是在單獨的Assembly中,因此只需要指出ProviderType就行了。
這樣,一個具有驗證功能的Provider就完成了,現在可以在頁面上放一個新的Security控件,比如Login控件,并指定它的MembershipProperty為MyMembershipProvider(或者也可以設置membership的defaultProvider屬性為MyMembershipProvider),打開Forms驗證,試試是不是已經能夠成功登陸了?