【问题标题】:Reset password using SMS service instead of Email in Asp.Net Core在 Asp.Net Core 中使用 SMS 服务而不是电子邮件重置密码
【发布时间】:2021-08-29 23:05:29
【问题描述】:

我想创建一个 Api 端点以通过 SMS 发送密码重置令牌。

当我们使用userManager.GeneratePasswordResetTokenAsync(user) 生成令牌时,令牌是一个长字符串,通常用于电子邮件消息中。此消息嵌入包含令牌作为参数的链接并发送给用户。用户点击链接后可以修改密码。

现在,我有一个问题:

  • 如何使用 SMS 服务而不是电子邮件来发送此令牌?
  • 我在 SMS 中使用使用 UserManagerGeneratePasswordResetTokenAsync(...) 创建的相同令牌是正确且推荐的方式,还是更好地使用另一个令牌提供程序来生成类似 6 位的短字符串?

【问题讨论】:

  • 如果您通过短信发送验证消息,您需要考虑到接收设备可能无法访问互联网,因为它可能不是智能手机。在这种情况下,可能无法单击链接或将验证码复制到浏览器中。因此,我建议使用简短的重置代码,可以很容易地手动输入。

标签: asp.net-core entity-framework-core single-page-application asp.net-core-identity


【解决方案1】:

根据我的经验,要重置用户的密码,您可以通过发送一个 6 位确认字符串来验证用户。

对于这种情况,您将遵循以下:

  1. 创建端点以通过 SMS 重置密码(在此操作中,您应该生成 6 位字符串并将值设置到具有有限生命周期(例如 1 分钟)的缓存(Redis 等)中,然后发送值通过短信发送到用户的电话号码。
  2. 您将拥有一个接收 6 位字符串作为确认短信的端点,该端点检查该用户的缓存并使用缓存中的现有值验证输入值
  3. 如果验证结果正常,您应该允许用户更改他/她的密码。

【讨论】:

    【解决方案2】:

    请注意,GeneratePasswordResetTokenAsyncGenerateChangeEmailTokenAsync 和类似方法在后台使用 GenerateUserTokenAsync(user, provider, purpose) 并指定了提供者和目的。

    我们可以使用GenerateUserTokenAsync(user, provider, purpose) 以我们想要的方式生成令牌。所以这将是我的终点:

        [HttpPost("sendResetPasswordToken")]
        [ServiceFilter(typeof(ModelValidationFilter))]
        public async Task<IActionResult> SendChangePasswordToken([FromBody] SendChangePasswordTokenDto dto)
        {
            var user = await _userManager.FindByNameAsync(dto.UserName);
            if (user is null)
                return UnprocessableEntity("something went wrong, contact support to resolve the problem");
    
    
            var token = await _userManager.GenerateUserTokenAsync(user, TokenOptions.DefaultPhoneProvider, "ResetPasswordPurpose");
            _SMSManager.SendResetPasswordToken(token, user.PhoneNumber);
            return NoContent();
        }
    

    我们将提供程序参数设置为TokenOptions.DefaultPhoneProvider,这是一个默认的电话令牌提供程序,并将目的参数设置为"ResetPasswordPurpose",这是一个指示令牌用途的字符串。

    为了验证这个令牌,我们使用VerifyUserTokenAsync(user, provider, purpose, token) 并提供适当的参数。所以这是我的 ResetPassword 端点:

        [HttpPost("resetPassword")]
        [ServiceFilter(typeof(ModelValidationFilter))]
        public async Task<IActionResult> ResetPassword([FromBody] ResetPasswordDto dto)
        {
            var user = await _userManager.FindByNameAsync(dto.SSN);
    
            if(user is null)
                return UnprocessableEntity("invalid user token");//actually user not found
    
            var tokenVerified = await _userManager.VerifyUserTokenAsync(user, TokenOptions.DefaultPhoneProvider, "ResetPasswordPurpose", dto.Token);
            if (!tokenVerified)
                return UnprocessableEntity("invalid user token");
    
            var token = await _userManager.GeneratePasswordResetTokenAsync(user);//new token for reseting password
            var result = await  _userManager.ResetPasswordAsync(user, token, dto.NewPassword);
            if (!result.Succeeded)
                return UnprocessableEntity("weak password");
    
            return NoContent();
        }
    

    【讨论】:

      猜你喜欢
      • 2018-06-29
      • 2020-04-11
      • 2020-02-15
      • 2019-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-11
      相关资源
      最近更新 更多