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

如何在.NET Core Identity Web应用中强制启用双因素认证(2FA)

1. 未注册自定义的ClaimsPrincipalFactory

你自定义的AdditionalUserClaimsPrincipalFactory没有替换Identity默认的声明工厂,所以CreateAsync方法永远不会被触发。需要在ConfigureServices的Identity注册逻辑中追加工厂注册:

services.AddIdentity<ApplicationUser, IdentityRole>(options => {
    // 保留你原来的Identity配置
})
.AddEntityFrameworkStores<你的DbContext类名>()
.AddDefaultTokenProviders()
// 追加这一行,注册自定义声明工厂
.AddClaimsPrincipalFactory<AdditionalUserClaimsPrincipalFactory>();

2. 授权策略逻辑不匹配需求

你当前的策略只校验amr声明为mfa,只能判断用户是否完成了2FA登录校验,无法覆盖「用户未开启2FA需要跳转设置」的场景。可以调整策略为同时处理两种场景:

services.AddAuthorization(options =>
{
    options.AddPolicy("TwoFactorEnabled", policy =>
    {
        policy.RequireAuthenticatedUser();
        policy.RequireAssertion(context =>
        {
            // 已完成2FA校验直接通过
            if (context.User.HasClaim(c => c.Type == "amr" && c.Value == "mfa"))
                return true;
            // 用户已开启2FA但未完成2FA校验,不通过
            if (context.User.HasClaim(c => c.Type == "TwoFactorEnabled" && c.Value == "true"))
                return false;
            // 未开启2FA的用户仅允许访问2FA设置、登出相关页面
            var httpContext = context.Resource as HttpContext;
            var path = httpContext?.Request.Path.Value ?? "";
            return path.StartsWith("/Identity/Account/Manage/TwoFactorAuthentication", StringComparison.OrdinalIgnoreCase)
                || path.StartsWith("/Identity/Account/Logout", StringComparison.OrdinalIgnoreCase);
        });
    });
});

3. 增加授权失败跳转逻辑

默认授权失败会直接返回403,你需要配置Cookie授权的事件,将未满足2FA要求的请求跳转到对应页面:

services.ConfigureApplicationCookie(options =>
{
    options.Events.OnRedirectToAccessDenied = context =>
    {
        var user = context.HttpContext.User;
        if (user.Identity.IsAuthenticated)
        {
            // 未开启2FA,跳转到2FA设置页
            if (!user.HasClaim(c => c.Type == "TwoFactorEnabled" && c.Value == "true"))
            {
                context.Response.Redirect("/Identity/Account/Manage/TwoFactorAuthentication");
            }
            // 已开2FA但未完成校验,跳转到2FA登录页
            else
            {
                context.Response.Redirect("/Identity/Account/LoginWith2fa");
            }
        }
        else
        {
            // 未登录走默认跳转逻辑
            context.Response.Redirect(context.RedirectUri);
        }
        return Task.CompletedTask;
    };
});

4. 全局应用策略(可选)

如果要强制全站所有页面都需要满足2FA要求,不需要每个控制器单独加特性,可以直接在路由配置中全局应用策略:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}")
        .RequireAuthorization("TwoFactorEnabled");
    endpoints.MapRazorPages().RequireAuthorization("TwoFactorEnabled");
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 05:39:01