为什么ResetPasswordAsync不工作? [英] Why is ResetPasswordAsync not working?

查看:1091
本文介绍了为什么ResetPasswordAsync不工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我打电话低于code,我总是 result.Succeeded = FALSE

  [HttpPost]
        [使用AllowAnonymous]
        [ValidateAntiForgeryToken]
        公共异步任务<&的ActionResult GT; ResetPassword(ResetPasswordViewModel模型)
        {
            如果(!ModelState.IsValid)
            {
                返回查看(模型);
            }
            VAR用户=等待UserManager.FindByNameAsync(model.Email);
            如果(用户== NULL)
            {
                //不要透露该用户不存在
                返回RedirectToAction(ResetPasswordConfirmation,账户);
            }
            字符串code =等待UserManager.GeneratePasswordResetTokenAsync(user.Id);
            VAR的结果=等待UserManager.ResetPasswordAsync(user.Id,code,model.Password);
            // VAR的结果=等待UserManager.ResetPasswordAsync(user.Id,型号为code,model.Password);
            如果(result.Succeeded)
            {
                返回RedirectToAction(ResetPasswordConfirmation,账户);
            }
            AddErrors(结果);
            返回查看();
        }

有关user.Id和密码的值是有效的。结果错误总是说无效令牌,我没有看到越好,因为我得到它,并立即检查它,它的错误。这仅仅是一个理智的测试 - 我通常通过电子邮件发送令牌到用户,但是,这不是工作或者

更新1 我这样在同一个控制器定义的UserManager:

 私人ApplicationSignInManager _signInManager;
    私人ApplicationUserManager _userManager;    公共AccessController的()
    {
    }    公共AccessController的(ApplicationUserManager的UserManager,ApplicationSignInManager signInManager)
    {
        的UserManager =的UserManager;
        SignInManager = signInManager;
    }    公共ApplicationSignInManager SignInManager
    {
        得到
        {
            返回_signInManager? 。HttpContext.GetOwinContext()获取< ApplicationSignInManager>();
        }
        私订
        {
            _signInManager =价值;
        }
    }    公共ApplicationUserManager的UserManager
    {
        得到
        {
            返回_userManager? 。HttpContext.GetOwinContext()GetUserManager< ApplicationUserManager>();
        }
        私订
        {
            _userManager =价值;
        }
    }

更新2 这是我ApplicationUserManager code:

 公共类ApplicationUserManager:&的UserManager LT; ApplicationUser>
{
    公共ApplicationUserManager(IUserStore< ApplicationUser>存储)
        :基地(存储)
    {
    }    公共静态ApplicationUserManager创建(IdentityFactoryOptions< ApplicationUserManager>选项,IOwinContext上下文)
    {
        VAR经理=新ApplicationUserManager(新UserStore< ApplicationUser>(context.Get< ApplicationDbContext>()));
        //配置用户名验证逻辑
        manager.UserValidator =新UserValidator< ApplicationUser>(经理)
        {
            AllowOnlyAlphanumericUserNames =假,
            RequireUniqueEmail =真
        };        //配置密码验证逻辑
        manager.PasswordValidator =新PasswordValidator
        {
            RequiredLength = 6,
            RequireNonLetterOrDigit = TRUE,
            RequireDigit = TRUE,
            RequireLowercase = TRUE,
            RequireUppercase = TRUE,
        };        //配置用户锁定默认
        manager.UserLockoutEnabledByDefault = TRUE;
        manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
        manager.MaxFailedAccessAttemptsBeforeLockout = 5;        //注册双因素身份验证提供者。此应用程序使用手机和电子邮件作为接收code用于验证用户的步骤
        //你可以写自己的供应商,并在这里插入。
        manager.RegisterTwoFactorProvider(手机code,新PhoneNumberTokenProvider< ApplicationUser>
        {
            MessageFormat =您的安全code是{0}
        });
        manager.RegisterTwoFactorProvider(电子邮件code,新EmailTokenProvider< ApplicationUser>
        {
            主题=安全code,
            BodyFormat =您的安全code是{0}
        });
        manager.EmailService =新EmailService();
        manager.SmsService =新SmsService();
        VAR dataProtectionProvider = options.DataProtectionProvider;
        如果(dataProtectionProvider!= NULL)
        {
            manager.UserTokenProvider =
                新DataProtectorTokenProvider< ApplicationUser>(dataProtectionProvider.Create(ASP.NET身份));
        }
        返回经理;
    }
}


解决方案

这是一个长镜头,但如果你的的UserManager 指出,它支持用户安全的邮票,然后确保这在数据库级用户具有有效的安全邮票,更具体地,它必须没有戳。

原因是,生成时code,如果邮票当属然后将其替换的String.Empty ,并在产生复位code使用。然而,验证复位code时,邮票从它的到来将直接比较一下来自数据库,所以你最终可能会比较的String.Empty 和失败的审定结果。

从ASP .NET身份2.2源$ C ​​$ C为 DataProtectorTokenProvider (它是在previous版相同):

  // GenerateAsync方法
如果(manager.SupportsUserSecurityStamp)
{
    印花税=等待manager.GetSecurityStampAsync(user.Id);
}
writer.Write(邮票??); //写成如果是null
// ValidateAsync方法
如果(manager.SupportsUserSecurityStamp)
{
    VAR expectedStamp =等待manager.GetSecurityStampAsync(user.Id).WithCurrentCulture();
    返回邮票== expectedStamp; //读为,但直接与空
}

When I call the code below, I always get 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();
        }

The values for user.Id and Password are valid. The result errors always say "Invalid Token" which I don't see as possible since I get it and instantly check it and it errors. This is just a sanity test - I normally send the token via email to the user but that wasn't working either.

UPDATE 1 I define the UserManager in the same controller like this:

    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 Here is my ApplicationUserManager code:

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

解决方案

This is a long shot, but if your UserManager states that it supports user security stamps then make sure that at the database level the user has a valid security stamp, more specifically, it must not have a NULL stamp.

The reason is that when generating the code, if the stamp comes as null then it is replaced with string.Empty and used in the generated reset code. However, when validating the reset code, the stamp coming from it will be compared directly to what comes from the database so you might end up comparing string.Empty to null and failing the validation as a consequence.

From ASP .NET Identity 2.2 source code for DataProtectorTokenProvider (it was the same in previous version):

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

这篇关于为什么ResetPasswordAsync不工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆