5节点本地Service Fabric集群中,如何用Redis共享Asp.Net Core Identity登录状态?
我之前在Service Fabric多节点环境里也碰到过一模一样的问题——登录后4/5概率直接跳回未登录页面,折腾了好几天才摸透核心原因:多节点之间没有共享认证票据的加密密钥和会话存储!下面是我亲测有效的最简实现步骤,照着来绝对能解决你的问题:
1. 先搞定DataProtection密钥共享(重中之重!)
AspNetCore Identity的认证票据是通过DataProtection加密后存在Cookie里的,Service Fabric每个节点默认会生成自己的独立密钥,导致其他节点根本解密不了这个Cookie,自然认不出已登录的用户。所以第一步必须让所有节点共享DataProtection的密钥,用Redis存储密钥是最适合集群环境的方案:
首先安装NuGet包:Microsoft.AspNetCore.DataProtection.StackExchangeRedis
然后在Program.cs里添加配置:
builder.Services.AddDataProtection() .PersistKeysToRedis(ConnectionMultiplexer.Connect("你的Redis连接字符串"), "DataProtection-Keys") .SetApplicationName("你的应用唯一名称"); // 所有节点的应用名称必须完全一致,否则密钥会被隔离
2. 配置Redis作为分布式缓存
如果你的应用用到了Session,或者Identity的「记住我」功能需要持久化,必须把分布式缓存指向Redis,确保所有节点的会话数据共享:
安装NuGet包:Microsoft.Extensions.Caching.StackExchangeRedis
然后添加配置:
builder.Services.AddStackExchangeRedisCache(options => { options.Configuration = "你的Redis连接字符串"; options.InstanceName = "你的应用实例标识"; // 可选,避免和其他应用的缓存数据冲突 });
3. 正确配置Identity与认证中间件
这里一定要注意中间件的顺序——UseAuthentication必须在UseAuthorization之前,且要在UseRouting之后,顺序错了认证逻辑直接失效。
先配置Identity:
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = false) .AddEntityFrameworkStores<ApplicationDbContext>(); // 替换成你自己的DbContext
再配置Cookie认证(Identity默认用Cookie认证,这里可以细化配置):
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.Cookie.Name = ".AspNetCore.Identity.Application"; // 保持默认名称,所有节点一致 options.Cookie.Domain = "你的统一域名"; // 比如".yourcompany.com",确保跨节点的Cookie能被浏览器共享 options.Cookie.HttpOnly = true; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // 生产环境务必开启HTTPS options.ExpireTimeSpan = TimeSpan.FromHours(2); options.SlidingExpiration = true; });
4. Session配置(如果你的应用需要用Session)
如果用到Session,要确保它使用分布式缓存,并且中间件顺序正确:
builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(30); options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; });
然后在中间件链里按顺序添加:
app.UseRouting(); app.UseSession(); // Session必须在UseAuthentication之前 app.UseAuthentication(); app.UseAuthorization(); app.MapRazorPages(); // 或者你的MVC/API端点映射
- 确保所有Service Fabric节点都能访问到同一个Redis实例/集群,不然共享就是空谈。
- 所有节点的
ApplicationName必须完全一致,DataProtection会根据这个名称隔离不同应用的密钥空间。 - 中间件顺序绝对不能乱:
UseRouting→UseSession→UseAuthentication→UseAuthorization→ 端点映射,这是AspNetCore的硬性规则。 - 如果是无状态服务,务必保证所有节点的配置(Redis连接字符串、应用名称等)完全统一,不要单独修改某个节点的本地配置。
我当时就是忽略了DataProtection的密钥共享,折腾了好几天,加上这一步之后,多节点的认证状态完全同步,再也没出现过登录后跳回未登录的情况!
内容的提问来源于stack exchange,提问作者caliver

