如何在AspNetCore EF6 Identity中实现多应用共享Cookie认证?
同一域名下多ASP.NET Core应用共享登录状态配置方案
核心问题分析
当前问题的根源是各应用的Data Protection密钥不共享,导致Cookie加密/解密无法互通;其次Cookie配置和Authentication的注册顺序存在不合理之处。
分步配置方案
1. 共享Data Protection密钥(必须)
所有应用必须使用相同的Data Protection密钥,否则无法解密彼此生成的Cookie,提供两种实现方式:
方式一:本地文件存储(开发环境适用)
在所有应用的Program.cs中添加以下配置,指定统一的密钥存储路径:
using Microsoft.AspNetCore.DataProtection; var builder = WebApplication.CreateBuilder(args); // 所有应用指向同一个本地密钥存储目录 builder.Services.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo(@"C:\SharedDataProtectionKeys")) .SetApplicationName("SharedAppIdentity"); // 所有应用使用相同的应用标识
注意:确保所有应用对该目录拥有读写权限。
方式二:SQL Server存储(生产环境适用)
如果采用SQL Server作为共享存储,先创建存储密钥的数据库表,再在所有应用中配置:
builder.Services.AddDataProtection() .PersistKeysToSqlServer(builder.Configuration.GetConnectionString("IdentityDb"), new SqlServerDataProtectionKeyRepositoryOptions { TableName = "DataProtectionKeys" }) .SetApplicationName("SharedAppIdentity");
所有应用需使用同一个数据库连接字符串。
2. 修正Cookie与Authentication配置
调整配置顺序,确保Identity注册后再配置共享Cookie,且所有应用的配置完全一致:
// 1. 注册Identity(所有应用引用共享类库中的ApplicationUser、DbContext) builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = false) .AddRoles<IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>(); // 2. 配置共享Cookie builder.Services.ConfigureApplicationCookie(options => { options.Cookie.Name = "AspNet.SharedCookie"; options.Cookie.Path = "/"; // 开发环境(localhost多端口):Domain设为null,浏览器自动适配端口 // 生产环境(子域名):设为".example.com"(开头的点匹配所有子域名) options.Cookie.Domain = builder.Environment.IsDevelopment() ? null : ".example.com"; options.Cookie.SameSite = SameSiteMode.Lax; options.Cookie.HttpOnly = true; options.Cookie.SecurePolicy = builder.Environment.IsDevelopment() ? CookieSecurePolicy.None : CookieSecurePolicy.Always; // 生产环境强制HTTPS // 登出时清除共享Cookie,实现同步登出 options.LogoutPath = "/Account/Logout"; options.Events.OnSigningOut = async context => { context.Response.Cookies.Delete(options.Cookie.Name, new CookieOptions { Domain = options.Cookie.Domain, Path = options.Cookie.Path }); await Task.CompletedTask; }; }); // 3. 注册Authentication(使用Identity默认Scheme,无需自定义名称) // 注:AddDefaultIdentity已自动注册Authentication,若需显式指定则用IdentityConstants.ApplicationScheme builder.Services.AddAuthentication(IdentityConstants.ApplicationScheme);
关键注意事项:
- 开发环境下不要强制设置
Cookie.Domain = "localhost",部分浏览器会出现兼容性问题,留空即可。- 生产环境子域名场景,必须设置
Cookie.Domain = ".example.com",确保所有子域名能读取共享Cookie。
3. 统一Identity核心组件
- 所有应用必须引用同一个共享类库中的
ApplicationUser、IdentityRole、ApplicationDbContext,保证实体结构和数据库上下文配置完全一致。 - 所有应用连接到同一个SQL Server身份数据库,确保用户数据统一。
4. 统一UserSecretsId(可选,推荐)
统一所有应用的UserSecretsId,避免开发环境下的配置冲突:
<PropertyGroup> <TargetFramework>net6.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <UserSecretsId>aspnet-SharedAppIdentity-CommonId</UserSecretsId> </PropertyGroup>
验证步骤
- 启动应用1(localhost:1000)并登录,确认浏览器中存在
AspNet.SharedCookie。 - 打开应用2(localhost:2000),直接访问需要身份验证的页面,验证是否已自动登录。
- 在任一应用中执行登出操作,返回另一应用确认已同步登出。
内容的提问来源于stack exchange,提问作者Pierre
相关产品推荐
相关产品推荐

