如何在.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
相关产品推荐
相关产品推荐

