2010-05-11 1 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")], то пользователь всегда отвергается, как будто он не в роли.

Любая идея о том, что может быть неправильным здесь?

Спасибо заранее,
Ile

ответ

1

Я подозреваю, что он пытается вызвать один из методов, которые вы еще не реализовали в SARoleProvider. Сначала я бы посмотрел на метод RoleExists. Поместите точку останова на каждый из методов в SARoleProvider, чтобы узнать, какой из них вызывается. Затем вы узнаете, какой метод (ы) вам нужно будет работать.

+0

Спасибо, я попробую это завтра утром! У меня нет привычки использовать контрольные точки, но в этом примере это хорошая идея! –

+0

altoguh, я не думаю, что проблема в RoleExists, потому что в учебнике я следил за работой менеджера ролей, и используются одни и те же методы реализации ...но я увижу завтра –

+0

Я нашел проблему благодаря отладке. Проблема была в контроллере в методе LogOn. Существует такая строка: FormsAuthentication.SetAuthCookie (userFullName, false); и он вставил неправильный параметр в файл cookie, вместо userFullName предположительно будет userName –

1

Я нашел это в отношении ролей и параметров пользователей для [Authorize] атрибут:

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

на основе кода в пользовательских авторизовать атрибут, мне кажется, что имя, вероятно, чувствительно к регистру. Вы пробовали:

[Authorize(Roles="Admin")] 

Вы также можете попробовать использовать пользовательский код в этой статье, так что вы можете получить от использования строк.

+0

Нет, это не так, потому что в базе данных оно также вставлено как «admin» –