首页 > 解决方案 > 验证重置密码令牌在一种方法中失败,但在 ASP.NET 身份中的另一种方法中有效

问题描述

在实际重置密码之前,我们正在尝试使用UserManager来生成并验证它。PasswordResetToken

第一种方法负责生成令牌,然后通过密码重置链接将其发送给用户。
令牌的生成工作正常,之后验证它时,VerifyUserTokenAsync返回 true(行://var result = await this.userManager.VerifyUserTokenAsync(user, TokenOptions.DefaultProvider, UserManager<User>.ResetPasswordTokenPurpose, token);

第二种方法是重置密码。我们没有使用,UserManager.ResetPassword因为我们的用户没有所有必填字段。VerfiyUserTokenAsync在此方法中调用时,false即使提供的标记与第一个方法中的完全相同,if 也会返回。

我们无法理解为什么它在第一种方法中有效,但在第二种方法中失败了......
任何线索都将受到高度赞赏。

提前致谢

[HttpPost("generatepasswordresettoken")]
[ProducesResponseType(StatusCodes.Status201Created)]
public async Task<IActionResult> GeneratePasswordResetToken([FromBody] ResetPasswordTokenRequest resetPasswordTokenRequest)
{
    var user = await this.userService.GetAsync(resetPasswordTokenRequest.Email);
    var token = await this.userManager.GeneratePasswordResetTokenAsync(user);
    //var result = await this.userManager.VerifyUserTokenAsync(user, TokenOptions.DefaultProvider, UserManager<User>.ResetPasswordTokenPurpose, token);

    return this.Ok(new GenerateResetPasswordTokeResponse {ResetPasswordToken = token, Email = resetPasswordTokenRequest.Email});
}



[HttpPut("resetpassword")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> ResetPassword([FromBody] ResetPasswordRequest resetPasswordRequest)
{
    var user = await this.userService.GetAsync(resetPasswordRequest.Email);
    if (await this.userManager.VerifyUserTokenAsync(user, TokenOptions.DefaultProvider, UserManager<User>.ResetPasswordTokenPurpose, resetPasswordRequest.ResetPasswordToken)) {
        var resetPasswordDomainModel = this.resetPasswordMapper.Map(resetPasswordRequest);
        if (await this.userService.ResetPasswordAsync(resetPasswordDomainModel)) {
            return this.Ok();
        }
    }

     return this.BadRequest("Couldn't reset password");
}

标签: c#.netasp.net-identityidentityserver4asp.net-core-3.1

解决方案


每个 SecurityToken 应该只对一个操作有效,并且VerifyUserTokenAsync方法的这种行为是一个优势。否则,您需要编写一些代码来自己控制这种行为。在您的情况下,您可以生成新令牌,然后将其传递给ResetPasswordAsync方法。

    [HttpPut("resetpassword")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async Task<IActionResult> ResetPassword([FromBody] ResetPasswordRequest resetPasswordRequest)
    {
        var user = await this.userService.GetAsync(resetPasswordRequest.Email);
        if (await this.userManager.VerifyUserTokenAsync(user, TokenOptions.DefaultProvider, UserManager<User>.ResetPasswordTokenPurpose, resetPasswordRequest.ResetPasswordToken))
        {
            var newtoken = userManager.GeneratePasswordResetTokenAsync(user);
            resetPasswordRequest.ResetPasswordToken = newtoken;
            var resetPasswordDomainModel = this.resetPasswordMapper.Map(resetPasswordRequest);
            if (await this.userService.ResetPasswordAsync(resetPasswordDomainModel))
            {
                return this.Ok();
            }
        }

        return this.BadRequest("Couldn't reset password");
    }

推荐阅读