如何获取非默认Authentication Scheme对应的ClaimsPrincipal?
问题原因
ASP.NET Core的认证中间件默认只会自动验证你指定的默认认证方案(也就是代码里的scheme1)。用scheme2登录后,虽然对应的Cookie已经生成,但中间件不会主动去验证这个非默认方案,所以context.User里不会有该方案的身份信息。另外你的代码里还有个隐藏问题:UseAuthentication()中间件的注册顺序错了,它被放在了路由定义之后,导致认证流程可能无法在端点处理前正常执行。
修复步骤
第一步:修正中间件顺序
把app.UseAuthentication()移到所有路由映射(MapGet等)的前面,确保认证流程在端点处理前完成:
var app = builder.Build(); // 先注册认证中间件 app.UseAuthentication(); // 再定义路由 app.MapGet("/", (HttpContext context) => { var result = JsonSerializer.Serialize(context.User, new JsonSerializerOptions { ReferenceHandler = ReferenceHandler.IgnoreCycles, WriteIndented = true }); return result; }); // 其他路由定义... app.Run();
第二步:配置多方案认证(二选一即可)
方案A:让中间件自动尝试验证所有Cookie方案
通过添加一个策略方案,让认证中间件根据请求中的Cookie自动选择要验证的方案,或者按顺序尝试所有方案。修改服务注册代码:
const string scheme1 = "cookie1"; const string scheme2 = "cookie2"; const string combinedScheme = "combined-cookies"; builder.Services.AddAuthentication(combinedScheme) // 添加策略方案,用于组合多个Cookie认证 .AddPolicyScheme(combinedScheme, "Combined Cookies", options => { // 根据请求中的Cookie选择要验证的方案 options.ForwardDefaultSelector = context => { // 如果存在scheme2的Cookie,优先验证scheme2;否则用默认的scheme1 if (context.Request.Cookies.ContainsKey(scheme2)) { return scheme2; } return scheme1; }; }) .AddCookie(scheme1, options => { options.Cookie.Name = scheme1; }) .AddCookie(scheme2, options => { options.Cookie.Name = scheme2; });
这样不管用哪个方案登录,中间件都会自动验证对应的Cookie,context.User就能正确获取到身份信息。
方案B:在端点手动验证非默认方案
如果只需要在特定端点验证scheme2,可以在端点方法里手动调用认证方法并合并身份:
app.MapGet("/", async (HttpContext context) => { // 手动验证两个方案 var scheme1Result = await context.AuthenticateAsync(scheme1); var scheme2Result = await context.AuthenticateAsync(scheme2); var principals = new List<ClaimsPrincipal>(); if (scheme1Result.Succeeded) principals.Add(scheme1Result.Principal); if (scheme2Result.Succeeded) principals.Add(scheme2Result.Principal); // 合并多个身份到context.User context.User = new ClaimsPrincipal(principals); var result = JsonSerializer.Serialize(context.User, new JsonSerializerOptions { ReferenceHandler = ReferenceHandler.IgnoreCycles, WriteIndented = true }); return result; });
额外说明
如果某些路由需要强制使用特定的认证方案,可以给路由添加授权策略,指定需要的方案:
app.MapGet("/only-scheme2", (HttpContext context) => { return JsonSerializer.Serialize(context.User, new JsonSerializerOptions { ReferenceHandler = ReferenceHandler.IgnoreCycles, WriteIndented = true }); }).RequireAuthorization(options => { options.AddPolicy("OnlyScheme2", policy => { policy.AuthenticationSchemes.Add(scheme2); policy.RequireAuthenticatedUser(); }); });
内容的提问来源于stack exchange,提问作者IvanD
相关产品推荐
相关产品推荐

