-
需求場景
- 網站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; } ... }
-