-
需求场景
- 网站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; } ... }
-