You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core Identity自定义令牌提供者如何生成6位数字令牌

问题描述

当前已配置自定义令牌提供者,相关代码及运行情况如下:

身份服务配置代码

services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
    options.Tokens.ProviderMap.Add("CustomEmailConfirmationTokenProvider",
                new TokenProviderDescriptor(typeof(CustomEmailConfirmationTokenProvider<ApplicationUser>)));
    options.Tokens.EmailConfirmationTokenProvider = "CustomEmailConfirmationTokenProvider";
})
    .AddEntityFrameworkStores<IdentityDbContext>()
    .AddTokenProvider<CustomEmailConfirmationTokenProvider<ApplicationUser>>("CustomEmailConfirmationTokenProvider");

自定义令牌提供者类代码

public class CustomEmailConfirmationTokenProvider<TUser> : DataProtectorTokenProvider<TUser> where TUser : class
{
    public CustomEmailConfirmationTokenProvider(IDataProtectionProvider dataProtectionProvider,IOptions<CustomEmailConfirmationTokenProviderOptions> options
        , ILogger<DataProtectorTokenProvider<TUser>> logger)
        : base(dataProtectionProvider, options,logger)
    { }
}
public class CustomEmailConfirmationTokenProviderOptions : DataProtectionTokenProviderOptions
{
    public CustomEmailConfirmationTokenProviderOptions()
    {
        Name = "CustomEmailConfirmationTokenProvider";
        TokenLifespan = TimeSpan.FromMinutes(1);
    }
}

令牌生成与验证代码

生成令牌:

var myToken = await usrManager.GenerateUserTokenAsync(user, "CustomEmailConfirmationTokenProvider", UserManager<object>.ResetPasswordTokenPurpose);

验证令牌:

var isValid = await usrManager.VerifyUserTokenAsync(userinfo, "CustomEmailConfirmationTokenProvider", 
                               UserManager<object>.ResetPasswordTokenPurpose, model.Token);

当前代码可正常运行,但生成的是长加密字符串:

CfDJ8IvIvIomoPJKkcJtJSNCN4wB6Fp82OPzYvkVaHtBzJBjY9EwOBt2nMg1WudWBTc1giurpRIXhSHeJTe3CLswJEOL7nng9Hd7H/ctDVNSEL5eBnzXVZpvSNmVCvgwIg3cwSNtcjjsYmGFA01EgyEkXXkBZg+jLDiEsKU8YgmaoQd5bOLE3WLopZo2lboG7dOnZv777SMHitbQNJ2SdRyZf2aMAybKAkHnKGIR3ZSyQXRM

需要将令牌修改为6位纯数字格式,请问需调整哪些部分?


解决方案

你当前使用的DataProtectorTokenProvider是基于数据保护API生成加密长令牌的,要生成6位数字验证码,需要替换为基于TOTP(基于时间的一次性密码)的令牌提供者,具体修改步骤如下:

1. 重写自定义令牌提供者类

替换原有的CustomEmailConfirmationTokenProvider和CustomEmailConfirmationTokenProviderOptions,改为继承TotpSecurityStampBasedTokenProvider<TUser>(ASP.NET Core Identity内置的数字验证码提供者):

public class CustomDigitTokenProvider<TUser> : TotpSecurityStampBasedTokenProvider<TUser> 
    where TUser : class
{
    public CustomDigitTokenProvider(ILogger<TotpSecurityStampBasedTokenProvider<TUser>> logger)
        : base(logger)
    {
    }
}

public class CustomDigitTokenProviderOptions : TotpSecurityStampBasedTokenProviderOptions
{
    public CustomDigitTokenProviderOptions()
    {
        Name = "CustomDigitTokenProvider";
        // 保留原有的1分钟有效期设置
        TokenLifespan = TimeSpan.FromMinutes(1);
        // 指定生成6位数字令牌
        Digits = 6;
    }
}

2. 更新身份服务配置

修改AddIdentity中的令牌提供者配置,替换为新的数字令牌提供者:

services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
    options.Tokens.ProviderMap.Add("CustomDigitTokenProvider",
                new TokenProviderDescriptor(typeof(CustomDigitTokenProvider<ApplicationUser>)));
    // 若需将此提供者作为默认邮件确认提供者,保留该行;按需调整即可
    options.Tokens.EmailConfirmationTokenProvider = "CustomDigitTokenProvider";
})
    .AddEntityFrameworkStores<IdentityDbContext>()
    .AddTokenProvider<CustomDigitTokenProvider<ApplicationUser>>("CustomDigitTokenProvider");

3. 更新令牌生成与验证代码

将令牌提供者名称替换为新的CustomDigitTokenProvider:
生成令牌:

var myToken = await usrManager.GenerateUserTokenAsync(user, "CustomDigitTokenProvider", UserManager<object>.ResetPasswordTokenPurpose);

验证令牌:

var isValid = await usrManager.VerifyUserTokenAsync(userinfo, "CustomDigitTokenProvider", 
                               UserManager<object>.ResetPasswordTokenPurpose, model.Token);

补充说明

  • TotpSecurityStampBasedTokenProvider会基于用户的安全戳和当前时间生成数字令牌,自动处理有效期校验,无需额外编写复杂逻辑。
  • 生成的令牌为纯6位数字字符串,完全符合需求。

内容的提问来源于stack exchange,提问作者Steven Sann

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 09:01:00