2012-01-27 29 views
3

到現在爲止,我已經在我的MVC3應用程序中完成了所有身份驗證工作,即驗證成員,並通過我的MemberRepository類創建成員。我現在想去官方,自定義MembershipProvider。到目前爲止,我只收集到我真的需要重寫此類的ValidateUser方法,並且因爲我沒有使用Login控件,所以我甚至不知道我絕對必須這樣做。我有多少MembershipProvider可以在MVC3中覆蓋

GetUserCreateUser重載方法帶來的不請自來的類型,以我的政黨,就像MembershipUser,在那裏我有一個精心製作的Member類。如果我不打算使用任何內置控件或管理工具,並且如果我這樣做,是否應該將我的覆蓋範圍限制在絕對必要的範圍內,請有人能爲我清除我是否真的需要自定義成員資格提供程序,這是什麼?

+1

[創建自定義成員資格提供程序](http://msdn.microsoft.com/en-us/library/ie/f1kyba5e.aspx) – 2012-01-27 15:43:19

+0

感謝@羅伯特,但那不能回答我的問題。我知道如何創建一個自定義的成員資格提供程序,並且要求我必須重寫基本方法還有多遠,或者我可以把它們留在NotImplementedException中,如果我能做到這一點,我真的需要一個自定義提供程序嗎? – ProfK 2012-01-27 16:06:37

回答

1

自定義的MembershipProvider

有可能獲得「免費」一些不錯的安全功能,如果您使用的是的MembershipProvider:您可以設置web.config中的每一個未驗證用戶重定向到登錄頁面,例如。或者,您可以將網站的特定部分設置爲僅對具有特定角色的用戶可見。如果這些功能對您的項目沒有意義,或者您已經以其他方式實現其等效功能,那麼實現自定義MembershipProvider沒有多大意義。你可能要考慮的是實際切換自己的實現使用SqlMembershipProvider的處理隸屬函數

SqlMembershipProvider的

另外一個可能性。

SqlMembershipProvider爲常見任務提供了一個強大的,經過驗證的平臺,這些任務很難重新創建每個項目:帳戶創建,驗證,刪除,鎖定,密碼重置,基本角色等。如果您已經完成所有這些你自己沒有使用SqlMembershipProvider,真的沒有任何一點創建一個只是爲了有它。但是,您應該小心,因爲您很有可能在自己的實施中做了錯誤的事情。例如,

  • 您是否將密碼存儲爲純文本或散列?
  • 您是否打開Rainbow Table攻擊,或者您是否在嘶嘶?
  • 在連續看到50次無效的密碼嘗試之後,您是否鎖定了人員的帳戶,或者您是否讓黑客不斷衝擊,直到他們暴力破解進入某人的帳戶?

SqlMembershipProvider已經以易於配置的方式解決了所有這些問題。您可能希望擁有自己的會員界面,DTO只需簡單包裝此默認MembershipProvider,以便您不必擔心這些各種問題。這樣,大多數代碼不必與這些「不請自來的類型」交互,但您仍然可以在後端獲得廣泛使用且經過驗證的安全框架的優勢。

+0

我想你很好地總結了它,謝謝。我不需要自定義提供程序,也不需要SqlProvider,但在很多情況下,您對該提供程序有很好的理解。 – ProfK 2012-01-28 06:52:56

2

這是我爲單元測試寫的一個。它儘可能小。

public class MockMembershipProvider : MembershipProvider 
{ 
    public IList<MembershipUser> Users { get; private set; } 

    private string _applicationName; 
    public override string ApplicationName 
    { 
     get 
     { 
      return _applicationName; 
     } 
     set 
     { 
      _applicationName = value; 
     } 
    } 

    public override bool ChangePassword(string username, string oldPassword, string newPassword) 
    { 
     throw new NotImplementedException(); 
    } 

    public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer) 
    { 
     throw new NotImplementedException(); 
    } 

    public override MembershipUser CreateUser(
     string username, 
     string password, 
     string email, 
     string passwordQuestion, 
     string passwordAnswer, 
     bool isApproved, 
     object providerUserKey, 
     out MembershipCreateStatus status) 
    { 
     var user = new MembershipUser(ProviderName, username, username, email, passwordQuestion, null, isApproved, false, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now); 
     Users.Add(user); 
     status = MembershipCreateStatus.Success; 
     return user; 
    } 

    public override bool DeleteUser(string username, bool deleteAllRelatedData) 
    { 
     var u = Users.Where(mu => mu.UserName.Equals(username, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); 
     if (u == null) return false; 
     Users.Remove(u); 
     return true; 
    } 

    public override bool EnablePasswordReset 
    { 
     get { return false; } 
    } 

    public override bool EnablePasswordRetrieval 
    { 
     get { return false; } 
    } 

    public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) 
    { 
     throw new NotImplementedException(); 
    } 

    public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) 
    { 
     var users = (from u in Users 
        where u.UserName.Equals(usernameToMatch, StringComparison.OrdinalIgnoreCase) 
        select u).ToList(); 
     totalRecords = users.Count; 
     return ToMembershipUserCollection(users); 
    } 

    public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) 
    { 
     var list = Users.Skip(pageIndex * pageSize).Take(pageSize); 
     totalRecords = list.Count(); 
     var result = new MembershipUserCollection(); 
     foreach (var u in list) 
     { 
      result.Add(u); 
     } 
     return result; 
    } 

    public override int GetNumberOfUsersOnline() 
    { 
     return Users.Count(); 
    } 

    public override string GetPassword(string username, string answer) 
    { 
     throw new NotImplementedException(); 
    } 

    public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) 
    { 
     return (from u in Users 
       where u.ProviderUserKey.ToString() == providerUserKey.ToString() 
       select u).FirstOrDefault(); 
    } 

    public override MembershipUser GetUser(string username, bool userIsOnline) 
    { 
     return (from u in Users 
       where u.UserName.Equals(username, StringComparison.OrdinalIgnoreCase) 
       select u).FirstOrDefault(); 
    } 

    public override string GetUserNameByEmail(string email) 
    { 
     return (from u in Users 
       where u.Email.Equals(email, StringComparison.OrdinalIgnoreCase) 
       select u.UserName).FirstOrDefault(); 
    } 

    public override int MaxInvalidPasswordAttempts 
    { 
     get { return 3; } 
    } 

    public override int MinRequiredNonAlphanumericCharacters 
    { 
     get { return 1; } 
    } 

    public override int MinRequiredPasswordLength 
    { 
     get { return 6; } 
    } 

    public override int PasswordAttemptWindow 
    { 
     get { return 10; } 
    } 

    public override MembershipPasswordFormat PasswordFormat 
    { 
     get { throw new NotImplementedException(); } 
    } 

    public override string PasswordStrengthRegularExpression 
    { 
     get { return null; } 
    } 

    public override string Name 
    { 
     get 
     { 
      return ProviderName; 
     } 
    } 

    public string ProviderName { get; set; } 

    public override string ResetPassword(string username, string answer) 
    { 
     throw new NotImplementedException(); 
    } 

    public override bool RequiresQuestionAndAnswer 
    { 
     get { return false; } 
    } 

    public override bool RequiresUniqueEmail 
    { 
     get { return true; } 
    } 

    private MembershipUserCollection ToMembershipUserCollection(IEnumerable<MembershipUser> users) 
    { 
     var result = new MembershipUserCollection(); 
     foreach (var u in users) 
     { 
      result.Add(u); 
     } 
     return result; 
    } 

    public override bool UnlockUser(string userName) 
    { 
     return true; 
    } 

    public override void UpdateUser(MembershipUser user) 
    { 
     var oldUser = Users.Where(u => u.UserName.Equals(user.UserName, StringComparison.OrdinalIgnoreCase)).Single(); 
     var index = Users.IndexOf(oldUser); 
     Users[index] = user; 
    } 

    public override bool ValidateUser(string username, string password) 
    { 
     throw new NotImplementedException(); 
    } 

    public MockMembershipProvider() 
    { 
     this.ProviderName = "MockMembershipProvider"; 
     Users = new List<MembershipUser>(); 
    } 
} 

public class FakeMembershipProvider : MockMembershipProvider 
{ 
    public FakeMembershipProvider(string name) 
    { 
     this.ProviderName = name ?? "MockMembershipProvider"; 
    } 
    public override MembershipUser CreateUser(
     string username, 
     string password, 
     string email, 
     string passwordQuestion, 
     string passwordAnswer, 
     bool isApproved, 
     object providerUserKey, 
     out MembershipCreateStatus status) 
    { 
     status = MembershipCreateStatus.ProviderError; 
     var user = new MockMembershipUser(); 
     user.Password = password; 
     user.User = username; 
     user.UserKey = providerUserKey; 
     Users.Add(user); 
     status = MembershipCreateStatus.Success; 
     return user; 
    } 
} 

public class MockMembershipUser : MembershipUser 
{ 
    public string Password { get; set; } 
    public string User { get; set; } 
    public object UserKey { get; set; } 

    public override string UserName { get { return User; } } 

    public override string Comment { get; set; } 

    public override object ProviderUserKey { get { return UserKey; } } 

    public override string GetPassword() 
    { 
     return Password ?? string.Empty; 
    } 
1

您是否想要將您的網絡應用程序與MembershipRepository分開?

如果是這樣,請在custom MembershipProvider中實現所有相同的功能,以便您的應用只取決於.NET Membership classes(除了web.config)。

如果不是,那麼不要打擾。

+0

>您是否想要將您的Web應用程序與MembershipRepository分離?不,不只是我的DI已經做到了。我剛剛得到的印象是某個地方需要提供商。 – ProfK 2012-01-27 16:28:37

+0

默認情況下,登錄控件將使用默認的MembershipProvider,但您可以輕鬆地覆蓋它。如果你不想使用會員助手類(和類似的角色),我不認爲你會通過創建一個自定義的提供者獲得任何東西。 – jrummell 2012-01-27 17:48:48

相關問題