ASP.NET MVC2实现自定义RoleManager问题

时间:2010-05-11 14:42:22

标签: asp.net-mvc-2 membership-provider

要创建自定义成员资格提供程序,我按照以下说明操作:
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.aspx

到目前为止,我已设法实现自定义成员资格提供程序,该部分工作正常。 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("ilija@ilija.com");

            // 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("ilija@ilija.com", roleNames[0].ToString());

            // Outputs True
            ViewData["r3"] = saRoleProvider.IsUserInRole("ilija@ilija.com", "admin"); 


            return View();
        }

如果我使用属性[Authorize],那么一切正常,但如果我使用[Authorize(Roles="admin")],那么用户总是被拒绝,就像他不在角色一样。

知道这里可能出现什么问题?

提前致谢,
ILE

2 个答案:

答案 0 :(得分:1)

我发现这与[授权]属性的角色和用户参数有关:

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

根据自定义Authorize属性中的代码,它看起来像名称可能区分大小写。你试过了吗?

[Authorize(Roles="Admin")]

您也可以尝试使用该文章中的自定义代码,这样您就可以远离使用字符串了。

答案 1 :(得分:1)

我怀疑它正试图调用你尚未在SARoleProvider中实现的方法之一。我先看一下RoleExists方法。在SARoleProvider中的每个方法上设置一个断点,以查看正在调用哪个方法。然后你就会知道你需要使用哪种方法。