如何减少Asp.Net Identity中的密码重置令牌长度?

sri*_*tha 8 c# asp.net asp.net-mvc-4 asp.net-identity

我使用Asp.Net Identity生成密码重置令牌.

string Token = userManager.GeneratePasswordResetToken(userId);
Run Code Online (Sandbox Code Playgroud)

上面的代码给了我一个很长的令牌.是否可以生成短长度的密码重置令牌?

Pec*_*can 7

您可以使用TotpSecurityStampBasedTokenProvider生成 6 位数字:

public class ResetPasswordTokenProvider : TotpSecurityStampBasedTokenProvider<OriIdentityUser>
{
    public const string ProviderKey = "ResetPassword";

    public override Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<OriIdentityUser> manager, OriIdentityUser user)
    {
        return Task.FromResult(false);
    }
}
Run Code Online (Sandbox Code Playgroud)

并在启动类中添加:

services.AddIdentity<IdentityUser, IdentityRole>(options =>
    {
        options.Tokens.PasswordResetTokenProvider = ResetPasswordTokenProvider.ProviderKey;
    })
    .AddDefaultTokenProviders()
    .AddTokenProvider<ResetPasswordTokenProvider>(ResetPasswordTokenProvider.ProviderKey);

Run Code Online (Sandbox Code Playgroud)


Kei*_*ith 1

您的密码重置令牌需要是加密随机的 - 这意味着给定一组已使用的令牌,下一个令牌应该无法猜测。它还需要覆盖足够大的一组可能值,以至于暴力尝试所有这些值的速度慢得不切实际。

您可以进行更改以使后者适用于较小的可能值集 - 例如,您可以在检查令牌之前向密码重置页面/操作添加 1 秒的延迟。您的用户几乎不会注意到很少使用的页面上的延迟,但攻击者将无法快速尝试大量令牌。

因此,首先您需要获得一个加密随机数:

var random = new byte[8];
using (var rng = System.Security.Cryptography.RandomNumberGenerator.Create())
    rng.GetBytes(random);
Run Code Online (Sandbox Code Playgroud)

我在这里放置了8字节,但是您可以将其设置为您想要的任何长度。

接下来,您需要将其制作成一个漂亮的可复制粘贴字符串。您可以通过 unicode 转换来做到这一点,但我发现 base 64 更可靠:

Convert.ToBase64String(random).TrimEnd('=');
Run Code Online (Sandbox Code Playgroud)

将其与8字节一起使用将为您提供 64 位可能值和 10 个字符的字符串。使用4将为您提供 32 位(可能足以在低安全性站点上进行缓慢的令牌检查)和 5 个字符的字符串。