【问题标题】:ASP.NET MVC2 Implementing Custom RoleManager problemASP.NET MVC2 实现自定义 RoleManager 问题
【发布时间】:2010-05-11 14:42:22
【问题描述】:

要创建自定义会员提供程序,我按照以下说明操作:
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;
        }
    }

网络配置

<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")],那么用户总是被拒绝,就像他不在角色一样。

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

提前致谢,
伊莱

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

    • 谢谢,我明天早上试试!我没有使用断点的习惯,但在这个例子中这是个好主意!
    • altoguh,我不认为 RoleExists 有问题,因为在教程中我遵循角色管理器的工作并使用相同的方法实现......但我明天会看到
    • 我通过调试发现了问题。问题出在方法 LogOn 中的 Controller 中。有这一行: FormsAuthentication.SetAuthCookie(userFullName, false);并且它向 cookie 插入了错误的参数,而不是 userFullName 假设是 userName
    【解决方案2】:

    我发现了关于 [Authorize] 属性的 Roles 和 Users 参数:

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

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

    [Authorize(Roles="Admin")]
    

    您也可以尝试使用那篇文章中的自定义代码,这样您就可以摆脱使用字符串。

    【讨论】:

    • 不,不是因为在数据库中它也被插入为“admin”
    猜你喜欢
    • 1970-01-01
    • 2011-04-24
    • 1970-01-01
    • 2011-01-21
    • 2016-07-31
    • 2012-08-21
    • 1970-01-01
    • 1970-01-01
    • 2018-01-28
    相关资源
    最近更新 更多