基于IdentityServer4实现SSO后Chrome新窗口重复登录问题解决
这种情况我碰到过好多次,大概率是Cookie的作用域/SameSite配置、Identity Server的会话管理或者MVC客户端的认证Cookie设置出了问题,咱们一步步来排查解决:
1. 调整Identity Server的Cookie配置
Identity Server自身的Cookie得设置正确的Domain和SameSite属性,才能让同一域名下的不同窗口共享登录状态。
在Identity Server的Startup.cs(或.NET 6+的Program.cs)中,找到AddIdentityServer的配置块,修改如下:
services.AddIdentityServer(options => { // 将Cookie的Domain设为根域名,比如你的应用域是example.com,就写".example.com" options.Authentication.CookieDomain = ".example.com"; // Chrome对跨窗口Cookie限制严格,SameSite设为None(必须配合HTTPS使用) options.Authentication.CookieSameSiteMode = SameSiteMode.None; }) .AddInMemoryClients(Config.Clients) // 保留原有其他配置...
划重点:
SameSiteMode.None必须在HTTPS环境下才生效。开发环境如果没配置HTTPS,可以临时在Chrome中关闭SameSite检查(地址栏输入chrome://flags/#same-site-by-default-cookies,设置为Disabled),但生产环境一定要启用HTTPS。
2. 修正MVC客户端的认证Cookie设置
MVC客户端的Cookie配置要和Identity Server保持一致,否则无法共享会话状态。
打开MVC客户端的Startup.cs(或Program.cs),调整AddAuthentication的配置:
services.AddAuthentication(options => { options.DefaultScheme = "Cookies"; options.DefaultChallengeScheme = "oidc"; }) .AddCookie("Cookies", options => { // 同样设置为根域名 options.Cookie.Domain = ".example.com"; options.Cookie.SameSite = SameSiteMode.None; // HTTPS环境下必须开启此项 options.Cookie.SecurePolicy = CookieSecurePolicy.Always; options.Cookie.HttpOnly = true; }) .AddOpenIdConnect("oidc", options => { options.Authority = "https://你的Identity Server地址"; options.ClientId = "mvc-client"; options.ClientSecret = "你的客户端密钥"; options.ResponseType = "code"; // 保存令牌到Cookie,确保会话持久化 options.SaveTokens = true; options.GetClaimsFromUserInfoEndpoint = true; // 回调地址要和Identity Server中客户端配置的完全一致 options.CallbackPath = "/signin-oidc"; options.SignedOutCallbackPath = "/signout-callback-oidc"; });
3. 检查Identity Server的客户端配置
打开Identity Server的Config.cs,确认MVC客户端的配置包含以下关键项:
new Client { ClientId = "mvc-client", ClientName = "MVC Client", AllowedGrantTypes = GrantTypes.Code, ClientSecrets = { new Secret("你的客户端密钥".Sha256()) }, RedirectUris = { "https://你的MVC客户端地址/signin-oidc" }, PostLogoutRedirectUris = { "https://你的MVC客户端地址/signout-callback-oidc" }, AllowedCorsOrigins = { "https://你的MVC客户端地址" }, AllowedScopes = { IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile, "你的API范围" }, // 允许离线访问,获取刷新令牌以保持长期登录状态 AllowOfflineAccess = true, // 按需调整令牌有效期,避免过短导致频繁重新登录 AccessTokenLifetime = 3600, IdentityTokenLifetime = 3600 };
4. 验证Chrome的Cookie权限设置
有时候是Chrome的第三方Cookie限制导致的:
- 打开Chrome设置 → 隐私和安全性 → Cookie和其他网站数据
- 要么关闭"阻止第三方Cookie"选项,要么将你的Identity Server和MVC客户端域名添加到"允许的网站"列表中
5. 确认Cookie状态是否正常
登录MVC客户端后,按F12打开开发者工具,切换到Application标签页查看Cookies:
- 确认存在
.AspNetCore.Cookies(MVC客户端的认证Cookie)和idsrv开头的(Identity Server的会话Cookie) - 检查这些Cookie的Domain是否为根域名,SameSite是否为None,Secure是否为true
按以上步骤配置完成后,Chrome新窗口访问MVC客户端应该就能自动识别已有的登录状态,无需重新登录了。
内容的提问来源于stack exchange,提问作者P John Raj

