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

如何在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. 启动应用1(localhost:1000)并登录,确认浏览器中存在AspNet.SharedCookie。
  2. 打开应用2(localhost:2000),直接访问需要身份验证的页面,验证是否已自动登录。
  3. 在任一应用中执行登出操作,返回另一应用确认已同步登出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 21:35:24