2010-05-11 138 views
1

要創建一個自定義的成員提供我按照這些指示:
How do I create a custom membership provider for ASP.NET MVC 2?
這些:
http://mattwrock.com/post/2009/10/14/Implementing-custom-Membership-Provider-and-Role-Provider-for-Authinticating-ASPNET-MVC-Applications.aspxASP.NET MVC2實現自定義RoleManager問題

到目前爲止,我已經成功地實現自定義的成員資格提供和該部分工作正常。 RoleManager仍然需要進行一些修改...

項目結構:

alt text http://img691.imageshack.us/img691/3875/21593096.gif

SAMembershipProvider.cs:

public class SAMembershipProvider : MembershipProvider 
    { 

     #region - Properties - 

     private int NewPasswordLength { get; set; } 
     private string ConnectionString { get; set; } 

     public bool enablePasswordReset { get; set; } 
     public bool enablePasswordRetrieval { get; set; } 
     public bool requiresQuestionAndAnswer { get; set; } 
     public bool requiresUniqueEmail { get; set; } 
     public int maxInvalidPasswordAttempts { get; set; } 
     public int passwordAttemptWindow { get; set; } 
     public MembershipPasswordFormat passwordFormat { get; set; } 
     public int minRequiredNonAlphanumericCharacters { get; set; } 
     public int minRequiredPasswordLength { get; set; } 
     public string passwordStrengthRegularExpression { get; set; } 

     public override string ApplicationName { get; set; } 

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

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

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

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

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

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

     public override MembershipPasswordFormat PasswordFormat 
     { 
      get { return passwordFormat; } 
     } 

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

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

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

     #endregion 

     #region - Methods - 

     public override void Initialize(string name, NameValueCollection config) 
     { 
      throw new NotImplementedException(); 
     } 

     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) 
     { 
      throw new NotImplementedException(); 
     } 

     public override bool DeleteUser(string username, bool deleteAllRelatedData) 
     { 
      throw new NotImplementedException(); 
     } 

     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) 
     { 
      throw new NotImplementedException(); 
     } 

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

     public override int GetNumberOfUsersOnline() 
     { 
      throw new NotImplementedException(); 
     } 

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

     public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) 
     { 
      throw new NotImplementedException(); 
     } 

     public override MembershipUser GetUser(string username, bool userIsOnline) 
     { 
      throw new NotImplementedException(); 
     } 

     public override string GetUserNameByEmail(string email) 
     { 
      throw new NotImplementedException(); 
     } 

     protected override void OnValidatingPassword(ValidatePasswordEventArgs e) 
     { 
      base.OnValidatingPassword(e); 
     } 

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

     public override bool UnlockUser(string userName) 
     { 
      throw new NotImplementedException(); 
     } 

     public override void UpdateUser(MembershipUser user) 
     { 
      throw new NotImplementedException(); 
     } 

     public override bool ValidateUser(string username, string password) 
     { 
      AccountRepository accountRepository = new AccountRepository(); 
      var user = accountRepository.GetUser(username); 

      if (string.IsNullOrEmpty(password.Trim())) return false; 
      if (user == null) return false; 

      //string hash = EncryptPassword(password); 
      var email = user.Email; 
      var pass = user.Password;    

      if (user == null) return false; 

      if (pass == password) 
      { 
       //User = user; 
       return true; 
      } 

      return false; 
     } 
     #endregion 

     protected string EncryptPassword(string password) 
     { 
      //we use codepage 1252 because that is what sql server uses 
      byte[] pwdBytes = Encoding.GetEncoding(1252).GetBytes(password); 
      byte[] hashBytes = System.Security.Cryptography.MD5.Create().ComputeHash(pwdBytes); 
      return Encoding.GetEncoding(1252).GetString(hashBytes); 
     } 

    } 

SARoleProvider.cs

public class SARoleProvider : RoleProvider 
    { 
     AccountRepository accountRepository = new AccountRepository(); 

     public override bool IsUserInRole(string username, string roleName) 
     { 
      return true; 
     } 
     public override string ApplicationName 
     { 
      get 
      { 
       throw new NotImplementedException(); 
      } 
      set 
      { 
       throw new NotImplementedException(); 
      } 
     } 
     public override void AddUsersToRoles(string[] usernames, string[] roleNames) 
     { 
      throw new NotImplementedException(); 
     } 
     public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames) 
     { 
      throw new NotImplementedException(); 
     } 
     public override void CreateRole(string roleName) 
     { 
      throw new NotImplementedException(); 
     } 
     public override bool DeleteRole(string roleName, bool throwOnPopulatedRole) 
     { 
      throw new NotImplementedException(); 
     } 
     public override bool RoleExists(string roleName) 
     { 
      throw new NotImplementedException(); 
     } 
     public override string[] GetRolesForUser(string username) 
     { 
      int rolesCount = 0; 
      IQueryable<RoleViewModel> rolesNames; 

      try 
      { 
       // get roles for this user from DB... 
       rolesNames = accountRepository.GetRolesForUser(username); 
       rolesCount = rolesNames.Count(); 

      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 

      string[] roles = new string[rolesCount]; 
      int counter = 0; 
      foreach (var item in rolesNames) 
      { 
       roles[counter] = item.RoleName.ToString(); 
       counter++; 
      } 

      return roles; 

     } 
     public override string[] GetUsersInRole(string roleName) 
     { 
      throw new NotImplementedException(); 
     } 

     public override string[] FindUsersInRole(string roleName, string usernameToMatch) 
     { 
      throw new NotImplementedException(); 

     } 
     public override string[] GetAllRoles() 
     { 
      throw new NotImplementedException(); 

     } 

    } 

AccountRepository.cs

public class RoleViewModel 
    { 
     public string RoleName { get; set; } 
    } 

    public class AccountRepository 
    { 
     private DB db = new DB(); 

     public User GetUser(string email) 
     { 
      return db.Users.SingleOrDefault(d => d.Email == email); 
     } 
     public IQueryable<RoleViewModel> GetRolesForUser(string email) 
     { 

      var result = (
         from role in db.Roles 
         join user in db.Users on role.RoleID equals user.RoleID 
         where user.Email == email 
         select new RoleViewModel 
         { 
          RoleName = role.Name 
         }); 

      return result; 
     } 
    } 

webconfig

<membership defaultProvider="SAMembershipProvider" userIsOnlineTimeWindow="15"> 
     <providers> 
     <clear/> 
     <add 
      name="SAMembershipProvider" 
      type="SA_Contacts.Membership.SAMembershipProvider, SA_Contacts" 
      connectionStringName ="ShinyAntConnectionString" 
      /> 
     </providers> 
    </membership> 

    <roleManager defaultProvider="SARoleProvider" enabled="true" cacheRolesInCookie="true"> 
     <providers> 
     <clear/> 
     <add 
      name="SARoleProvider" 
      type="SA_Contacts.Membership.SARoleProvider" 
      connectionStringName ="ShinyAntConnectionString" 
      /> 
     </providers> 
    </roleManager> 

AccountController.cs:

public class AccountController : Controller 
    { 
     SAMembershipProvider provider = new SAMembershipProvider(); 
     AccountRepository accountRepository = new AccountRepository(); 

     public AccountController() 
     { 
     } 

     public ActionResult LogOn() 
     { 
      return View(); 
     } 

     [AcceptVerbs(HttpVerbs.Post)] 
     public ActionResult LogOn(string userName, string password, string returnUrl) 
     { 

      if (!ValidateLogOn(userName, password)) 
      { 
       return View(); 
      } 

      var user = accountRepository.GetUser(userName); 
      var userFullName = user.FirstName + " " + user.LastName; 

      FormsAuthentication.SetAuthCookie(userFullName, false); 
      if (!String.IsNullOrEmpty(returnUrl) && returnUrl != "/") 
      { 
       return Redirect(returnUrl); 
      } 
      else 
      { 
       return RedirectToAction("Index", "Home"); 
      } 
     } 

     public ActionResult LogOff() 
     { 

      FormsAuthentication.SignOut(); 
      return RedirectToAction("Index", "Home"); 
     } 

     private bool ValidateLogOn(string userName, string password) 
     { 
      if (String.IsNullOrEmpty(userName)) 
      { 
       ModelState.AddModelError("username", "You must specify a username."); 
      } 
      if (String.IsNullOrEmpty(password)) 
      { 
       ModelState.AddModelError("password", "You must specify a password."); 
      } 
      if (!provider.ValidateUser(userName, password)) 
      { 
       ModelState.AddModelError("_FORM", "The username or password provided is incorrect."); 
      } 

      return ModelState.IsValid; 
     } 
    } 

在一些測試控制器我有以下幾點:

[Authorize] 
    public class ContactsController : Controller 
    { 

     SAMembershipProvider saMembershipProvider = new SAMembershipProvider(); 
     SARoleProvider saRoleProvider = new SARoleProvider(); 

     // 
     // GET: /Contact/ 

     public ActionResult Index() 
     { 
      string[] roleNames = Roles.GetRolesForUser("[email protected]"); 

      // Outputs admin 
      ViewData["r1"] = roleNames[0].ToString(); 

      // Outputs True 
      // I'm not even sure if this method is the same as the one below 
      ViewData["r2"] = Roles.IsUserInRole("[email protected]", roleNames[0].ToString()); 

      // Outputs True 
      ViewData["r3"] = saRoleProvider.IsUserInRole("[email protected]", "admin"); 


      return View(); 
     } 

如果我使用屬性[Authorize]然後一切工作正常,但如果我使用[Authorize(Roles="admin")]然後用戶總是被拒絕,就像他不在角色中一樣。

有什麼想法可能是錯誤的嗎?

由於提前,

回答

1

我懷疑它試圖調用你還沒有在SARoleProvider中實現的方法之一。我會首先查看RoleExists的方法。在SARoleProvider的每個方法上設置一個斷點來查看哪一個被調用。然後你會知道你需要使用哪種方法。

+0

謝謝,明天早上我會試試!我沒有使用斷點的習慣,但在這個例子中,這是個好主意! – 2010-05-11 15:59:31

+0

altoguh,我不認爲問題出現在RoleExists中,因爲在教程中,我遵循角色管理器的工作原理並使用相同的方法實現...但我明天會看到 – 2010-05-11 16:48:55

+0

由於調試,我發現這個問題。問題出在LogOn方法中的Controller中。有這樣一行:FormsAuthentication.SetAuthCookie(userFullName,false);並且它將錯誤的參數插入到cookie中,而不是userFullName,假設是userName – 2010-05-12 06:32:08

1

我發現這對於角色和用戶參數爲[授權]屬性:

http://www.robertschultz.org/2009/07/29/multiple-roles-with-authorize-attribute-using-enums-in-asp-net-mvc/

基於在自定義授權屬性的代碼,它看起來像我的名字可能區分大小寫。您是否嘗試過:

[Authorize(Roles="Admin")] 

你也可以嘗試使用本文中的自定義代碼,以便您可以使用字符串脫身。

+0

不,這不是因爲在數據庫中它也插入爲「admin」 – 2010-05-11 14:55:15