ASP.NET成员身份更改密码不起作用

JK.*_*JK. 12 .net c# asp.net-mvc asp.net-membership

我有这个代码用于在用户单击密码重置按钮时更改用户的密码(使用额外的代码登录到ELMAH,这样我就可以尝试找出出错的地方).

这是在ASP.NET MVC 2中,使用标准的aspnet成员资格提供程序,使用这样的简单视图:

New Password:     ______
Confirm Password: ______
[Reset] [Cancel]
Run Code Online (Sandbox Code Playgroud)

此视图的路径是/Account/Reset/guid,其中guid是aspnet成员资格数据库中的用户ID.

代码的关键部分是它调用的地方user.ChangePassword().您可以看到它在成功时记录消息.问题是对于某些用户,会记录成功消息,但他们无法使用新密码登录.对于其他用户,它会记录成功消息,并且可以登录.

if (user.ChangePassword(pwd, confirmPassword))
{
    ErrorSignal.FromCurrentContext().Raise(
        new Exception("ResetPassword - changed successfully!"));
    return Json(new { 
        Msg = "You have reset your password successfully." }, 
        JsonRequestBehavior.AllowGet);
 }
Run Code Online (Sandbox Code Playgroud)

完整的代码清单是:

[HttpPost]
public JsonResult ResetPassword(string id, string newPassword, string confirmPassword)
{
    ErrorSignal.FromCurrentContext().Raise(new Exception("ResetPassword started for " + id));

    ViewData["PasswordLength"] = Membership.MinRequiredPasswordLength;

    if (string.IsNullOrWhiteSpace(newPassword))
    {
        ErrorSignal.FromCurrentContext().Raise(
            new Exception("ResetPassword - new password was blank."));
        ModelState.AddModelError("_FORM", "Please enter a new password.");
        return Json(new { Errors = ModelState.Errors() }, JsonRequestBehavior.AllowGet);
    }

    if (newPassword.Length < Membership.MinRequiredPasswordLength)
    {
        ErrorSignal.FromCurrentContext().Raise(
            new Exception("ResetPassword - new password was less than minimum length."));
        ModelState.AddModelError("_FORM", 
            string.Format("The password must be at least {0} characters long.", 
            Membership.MinRequiredPasswordLength));
        return Json(new { Errors = ModelState.Errors() }, JsonRequestBehavior.AllowGet);
    }

    if (string.IsNullOrWhiteSpace(confirmPassword))
    {
        ErrorSignal.FromCurrentContext().Raise(
            new Exception("ResetPassword - confirm password was blank."));
        ModelState.AddModelError("_FORM", 
            "Please enter the same new password in the confirm password textbox.");
        return Json(new { Errors = ModelState.Errors() }, JsonRequestBehavior.AllowGet);
    }

    if (confirmPassword.Length < Membership.MinRequiredPasswordLength)
    {
        ErrorSignal.FromCurrentContext().Raise(
            new Exception("ResetPassword - confirm password was less than minimum length."));
        ModelState.AddModelError("_FORM", 
            string.Format("The password must be at least {0} characters long.", 
            Membership.MinRequiredPasswordLength));
        return Json(new { Errors = ModelState.Errors() }, JsonRequestBehavior.AllowGet);
    }

    if (confirmPassword != newPassword)
    {
        ErrorSignal.FromCurrentContext().Raise(
            new Exception("ResetPassword - new password did not match the confirm password."));
        ModelState.AddModelError("_FORM", "Please enter the same password again.");
        return Json(new { Errors = ModelState.Errors() }, JsonRequestBehavior.AllowGet);
    }

    bool isMatch = ValidationHelper.IsGUID(id);
    if (string.IsNullOrWhiteSpace(id) || !isMatch)
    {
        ErrorSignal.FromCurrentContext().Raise(
            new Exception("ResetPassword - id was not a guid."));
        ModelState.AddModelError("_FORM", "An invalid ID value was passed in through the URL");
    }
    else
    {
        //ID exists and is kosher, see if this user is already approved
        //Get the ID sent in the querystring
        Guid userId = new Guid(id);

        try
        {
            //Get information about the user
            MembershipUser user = Membership.GetUser(userId);
            if (user == null)
            {
                //could not find the user
                ErrorSignal.FromCurrentContext().Raise(
                    new Exception("ResetPassword - could not find user by id " + id));
                ModelState.AddModelError("_FORM", 
                    "The user account can not be found in the system.");
            }
            else
            {
                ErrorSignal.FromCurrentContext().Raise(
                    new Exception("ResetPassword - user is " + user.UserName));
                string pwd = user.ResetPassword();

                if (user.ChangePassword(pwd, confirmPassword))
                {
                    ErrorSignal.FromCurrentContext().Raise(
                        new Exception("ResetPassword - changed successfully!"));
                    return Json(new { 
                        Msg = "You have reset your password successfully." }, 
                        JsonRequestBehavior.AllowGet);
                }
                ErrorSignal.FromCurrentContext().Raise(
                    new Exception("ResetPassword 
                    - failed to change the password, for an unknown reason"));
            }
        }
        catch (Exception ex)
        {
            ErrorSignal.FromCurrentContext().Raise(
                new Exception("ResetPassword: " + ex));
            return Json(new { Error = ex.Message + " -> " 
                + ex.InnerException.Message }, JsonRequestBehavior.AllowGet);
        }
    }

    return Json(new { Errors = ModelState.Errors() }, JsonRequestBehavior.AllowGet);
}
Run Code Online (Sandbox Code Playgroud)

编辑:添加赏金以尝试解决此问题.这是我的问题列表中最烦人的问题之一,我不知道如何继续.

Jef*_*ata 15

如果用户需要重置密码,则他们的帐户有可能被锁定,因为无效的尝试次数过多.如果是这种情况,则密码正在成功重置,但用户无法登录,直到锁定条件被清除.

尝试检查MembershipUser.IsLockedOut:

在PasswordAttemptWindow中达到MaxInvalidPasswordAttempts时,用户最常被锁定,并且无法通过ValidateUser方法验证.

要将此属性设置为false并让用户尝试再次登录,可以使用UnlockUser方法.

编辑

你也检查过IsApproved吗?身份验证将失败,这是false针对用户的.

此外,假设默认情况下成员资格提供程序,您的意思是SqlMembershipProvider,您是否可以针对您的数据库运行以下查询并确保一切正常?

select IsApproved, IsLockedOut, FailedPasswordAttemptCount
from aspnet_Membership
where ApplicationId = @yourApplicationId and UserId = @userId
Run Code Online (Sandbox Code Playgroud)

尝试登录以验证IsApprovedIsLockedOut确定之前尝试执行查询.还要注意值FailedPasswordAttemptCount.

尝试登录,然后再次运行查询.如果登录失败,是否FailedPasswordAttemptCount已增加值?

您还可以在PasswordFormataspnet_Membership表中查看并确保它是正确的值,具体取决于您使用的格式(0表示清除,1表示Hashed,2表示加密).