2010-05-11 6 views
1

Pour créer un fournisseur d'appartenances personnalisé J'ai suivi ces instructions:
How do I create a custom membership provider for ASP.NET MVC 2?
et ces:
http://mattwrock.com/post/2009/10/14/Implementing-custom-Membership-Provider-and-Role-Provider-for-Authinticating-ASPNET-MVC-Applications.aspxASP.NET MVC2 mise en œuvre personnalisée roleManager problème

Jusqu'à présent, je suis parvenu à mettre en œuvre fournisseur d'appartenances personnalisé et cette partie fonctionne bien. RoleManager a encore besoin de quelques modifications ...

Structure du projet:

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; 
     } 
    } 

Dans certains contrôleur de test je suit:

[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(); 
     } 

Si j'utilise l'attribut [Authorize] alors tout fonctionne bien, mais si j'utilise [Authorize(Roles="admin")] alors l'utilisateur est toujours rejeté, comme s'il n'était pas dans le rôle.

Une idée de ce qui pourrait être mauvais ici?

Merci à l'avance,
Ile

Répondre

1

Je suppose qu'il essaye d'appeler l'une des méthodes que vous avez encore à implémenter dans SARoleProvider. Je regarderais d'abord la méthode RoleExists. Mettez un point d'arrêt sur chacune des méthodes dans SARoleProvider pour voir lequel est appelé. Ensuite, vous saurez quelle (s) méthode (s) vous devrez utiliser.

+0

Merci, je vais essayer demain matin! Je n'ai pas l'habitude d'utiliser des points d'arrêt, mais dans cet exemple c'est une bonne idée! –

+0

altoguh, je ne pense pas que le problème est dans RoleExists parce que dans le tutoriel j'ai suivi le gestionnaire de rôles fonctionne et les mêmes implémentations de méthodes sont utilisées ...mais je verrai demain –

+0

J'ai trouvé le problème grâce au débogage. Le problème était dans Controller dans la méthode LogOn. Il y a cette ligne: FormsAuthentication.SetAuthCookie (userFullName, false); et il a inséré un mauvais paramètre à cookie, au lieu de userFullName il est supposé être userName –

1

J'ai trouvé ce qui concerne les rôles et les paramètres des utilisateurs pour l'attribut [Authorize]:

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

Basé sur le code dans la coutume Autorisez attribut, il me semble que le nom est probablement sensible à la casse. Avez-vous essayé:

[Authorize(Roles="Admin")] 

Vous pouvez également essayer d'utiliser le code personnalisé dans cet article afin que vous puissiez échapper à l'aide de chaînes.

+0

non, ce n'est pas parce que dans la base de données il est également inséré comme "admin" –