netcore 实现跨应用的分布式session
-
需求场景
- 网站a,域名为 a.site.com
- 网站b, 域名为 b.site.com
- 需要在a、b两个站点之间共享session
-
解决方案
- 使用redis作为分布式缓存存储
- 设置sessionId cookie 保存的域名,使得两个网站钧能够读取到相同的sessionId
services.AddDistributedRedisCache(options => //使用redis { options.Configuration = $"{conf},defaultDatabase={dbId}"; }); services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(30); options.Cookie.Domain = "site.com"; });
-
自定义SessionMiddleware
-
由于Asp.net 自带的SessionMiddleware中间中对sessionid做了加密处理,导致不同应用虽然sessionId相同,但是并不能成功的共享Session,具体详件SessionMiddleware源码,其中使用了CookieProtection类的对sessionId进行了加密
-
public async Task Invoke(HttpContext context) { .... if (string.IsNullOrWhiteSpace(sessionKey) || sessionKey.Length != SessionKeyLength) { // No valid cookie, new session. var guidBytes = new byte[16]; CryptoRandom.GetBytes(guidBytes); sessionKey = new Guid(guidBytes).ToString(); cookieValue = CookieProtection.Protect(_dataProtector, sessionKey); var establisher = new SessionEstablisher(context, cookieValue, _options); tryEstablishSession = establisher.TryEstablishSession; isNewSessionKey = true; } ... }
-
由于SessionMiddleware是直接依赖类CookieProtection,因此需要重新实现自己的中间件来处理session,比如实现一个MySessionMiddleware,即可实现session共享
public async Task Invoke(HttpContext context) { .... if (string.IsNullOrWhiteSpace(sessionKey) || sessionKey.Length != SessionKeyLength) { // No valid cookie, new session. var guidBytes = new byte[16]; CryptoRandom.GetBytes(guidBytes); sessionKey = new Guid(guidBytes).ToString(); cookieValue = Md5(sessionKey);//此处可以使用自己的加密规则,重要的是保证不同的应用,通过加密规则生成的值是相同的 var establisher = new SessionEstablisher(context, cookieValue, _options); tryEstablishSession = establisher.TryEstablishSession; isNewSessionKey = true; } ... }
-
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步