为什么ResetPasswordAsync不起作用



当我调用下面的代码时,我总是得到result.Succeeded = false

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return View(model);
            }
            var user = await UserManager.FindByNameAsync(model.Email);
            if (user == null)
            {
                // Don't reveal that the user does not exist
                return RedirectToAction("ResetPasswordConfirmation", "Account");
            }
            string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
            var result = await UserManager.ResetPasswordAsync(user.Id, code, model.Password);
            //var result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);
            if (result.Succeeded)
            {
                return RedirectToAction("ResetPasswordConfirmation", "Account");
            }
            AddErrors(result);
            return View();
        }

用户的值。Id和密码有效。结果错误总是说"无效令牌",我认为这是不可能的,因为我得到了它,并立即检查它和它的错误。这只是一个健全性测试——我通常通过电子邮件将令牌发送给用户,但这也不起作用。

UPDATE 1我在同一个控制器中定义UserManager,如下所示:

    private ApplicationSignInManager _signInManager;
    private ApplicationUserManager _userManager;
    public AccessController()
    {
    }
    public AccessController(ApplicationUserManager userManager, ApplicationSignInManager signInManager)
    {
        UserManager = userManager;
        SignInManager = signInManager;
    }
    public ApplicationSignInManager SignInManager
    {
        get
        {
            return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
        }
        private set
        {
            _signInManager = value;
        }
    }
    public ApplicationUserManager UserManager
    {
        get
        {
            return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
        }
        private set
        {
            _userManager = value;
        }
    }

UPDATE 2这是我的ApplicationUserManager代码:

public class ApplicationUserManager : UserManager<ApplicationUser>
{
    public ApplicationUserManager(IUserStore<ApplicationUser> store)
        : base(store)
    {
    }
    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
    {
        var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
        // Configure validation logic for usernames
        manager.UserValidator = new UserValidator<ApplicationUser>(manager)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };
        // Configure validation logic for passwords
        manager.PasswordValidator = new PasswordValidator
        {
            RequiredLength = 6,
            RequireNonLetterOrDigit = true,
            RequireDigit = true,
            RequireLowercase = true,
            RequireUppercase = true,
        };
        // Configure user lockout defaults
        manager.UserLockoutEnabledByDefault = true;
        manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
        manager.MaxFailedAccessAttemptsBeforeLockout = 5;
        // Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
        // You can write your own provider and plug it in here.
        manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
        {
            MessageFormat = "Your security code is {0}"
        });
        manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
        {
            Subject = "Security Code",
            BodyFormat = "Your security code is {0}"
        });
        manager.EmailService = new EmailService();
        manager.SmsService = new SmsService();
        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider = 
                new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
        return manager;
    }
}

这是一个很长的机会,但如果您的UserManager声明它支持用户安全戳,那么请确保在数据库级别用户具有有效的安全戳,更具体地说,它不能具有NULL戳。

原因是在生成代码时,如果标记为null,则它将被替换为string.Empty,并用于生成的重置代码。但是,在验证重置代码时,来自重置代码的戳将直接与来自数据库的戳进行比较,因此您可能会将string.Emptynull进行比较,从而导致验证失败。

来自DataProtectorTokenProvider的ASP.NET Identity 2.2源代码(与以前的版本相同):

// GenerateAsync method
if (manager.SupportsUserSecurityStamp)
{
    stamp = await manager.GetSecurityStampAsync(user.Id);
}
writer.Write(stamp ?? ""); // Written as "" if null

// ValidateAsync method
if (manager.SupportsUserSecurityStamp)
{
    var expectedStamp = await manager.GetSecurityStampAsync(user.Id).WithCurrentCulture();
    return stamp == expectedStamp; // Read as "" but compared directly to null
}

相关内容

  • 没有找到相关文章

最新更新