ASP.NET Core Web API无法识别Blazor Server的Identity Cookie认证
我有两个ASP.NET Core应用:
- 已配置Identity认证的Blazor Server应用(认证功能正常)
- 需要与Blazor应用共享认证Cookie的Web API
目前API无法完成用户认证——即便用户已在Blazor应用中登录,User.FindFirstValue(ClaimTypes.NameIdentifier)始终返回null。
Blazor Server的Program.cs配置
builder.Services.AddAuthentication(options => { options.DefaultScheme = IdentityConstants.ApplicationScheme; options.DefaultSignInScheme = IdentityConstants.ExternalScheme; }) .AddIdentityCookies(); builder.Services.AddIdentityCore<User>(options => options.SignIn.RequireConfirmedAccount = false) .AddRoles<IdentityRole>() .AddEntityFrameworkStores<UserdbContext>() .AddSignInManager() .AddDefaultTokenProviders(); var app = builder.Build(); app.MapAdditionalIdentityEndpoints();
Web API的Program.cs配置
builder.Services.AddAuthentication(options => { options.DefaultScheme = IdentityConstants.ApplicationScheme; options.DefaultSignInScheme = IdentityConstants.ExternalScheme; }) .AddIdentityCookies(); builder.Services.AddIdentityCore<BlazorProject.Data.User>(options => { options.SignIn.RequireConfirmedAccount = false; }) .AddRoles<IdentityRole>() .AddEntityFrameworkStores<UserdbContext>() .AddSignInManager() .AddDefaultTokenProviders(); var app = builder.Build(); app.UseAuthentication(); app.UseAuthorization();
认证失败的API控制器代码
[HttpPost] public async Task<IActionResult> AddUserDeliveryMethod(int methodId) { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); // Always null // ... }
已尝试的操作:
- 两个应用使用同一数据库与Identity配置
- Blazor应用认证功能完全正常
- 已为两个应用配置相同的Cookie方案
核心疑问:为何Web API无法识别Blazor Server应用的认证Cookie?如何让二者正确共享认证状态?要求保留基于Cookie的认证方式,不采用JWT令牌方案。
要让两个ASP.NET Core应用共享Identity认证Cookie,你需要补充以下关键配置,这些是当前代码中缺失的核心项:
1. 配置DataProtection共享加密密钥
ASP.NET Core的DataProtection系统负责加密认证Cookie,两个应用必须使用相同的密钥环才能解密彼此的Cookie。
在两个应用的Program.cs中添加DataProtection配置,指定共享的密钥存储位置(生产环境建议用分布式存储如Azure Blob、Redis,本地开发可使用共享文件夹):
// 本地开发示例,生产环境替换为可靠的共享存储 builder.Services.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo(@"C:\SharedAuthKeys")) .SetApplicationName("SharedAuthApp"); // 两个应用必须使用完全相同的ApplicationName
2. 统一Cookie的Domain和SameSite设置
需要确保Cookie的Domain设置为两个应用共同的父域名(例如Blazor应用为app.yourdomain.com,API为api.yourdomain.com,则Domain设为.yourdomain.com),同时SameSite属性要适配跨域场景。
修改两个应用的AddIdentityCookies配置,显式指定Cookie选项:
builder.Services.AddAuthentication(options => { options.DefaultScheme = IdentityConstants.ApplicationScheme; options.DefaultSignInScheme = IdentityConstants.ExternalScheme; }) .AddIdentityCookies(options => { options.ApplicationCookie.Configure(cookie => { cookie.Cookie.Domain = ".yourdomain.com"; // 本地开发可留空(localhost场景) cookie.Cookie.SameSite = SameSiteMode.Lax; // 跨域场景推荐用Lax,HTTPS环境可设为None cookie.Cookie.SecurePolicy = CookieSecurePolicy.Always; // 生产环境强制HTTPS cookie.Cookie.HttpOnly = true; cookie.Cookie.Path = "/"; // 确保所有子路径都能访问Cookie }); });
3. 确认API端中间件顺序
确保UseAuthentication和UseAuthorization的顺序正确,必须在UseRouting之后、端点映射之前:
var app = builder.Build(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); // 控制器路由必须在认证中间件之后
4. 验证Identity用户类一致性
确保两个应用中的User类(Blazor的User和API的BlazorProject.Data.User)完全一致,包括命名空间、属性定义,否则Identity解析Claims时会出现匹配问题。
5. 本地开发额外检查
如果是localhost环境,确保两个应用使用同一个浏览器会话,且浏览器未禁用Cookie;不同端口的localhost应用,Cookie Domain留空即可正常共享。
完成以上配置后,Web API就能正确识别Blazor Server生成的认证Cookie,User.FindFirstValue(ClaimTypes.NameIdentifier)将返回正确的用户ID。
内容的提问来源于stack exchange,提问作者PeacefulWarrior22

