前言
公司使用id4進行認證授權,已經有一年了,但是今年2月份突然出現某些用戶登錄之后,無法跳轉回原網頁,還是停留在登錄頁。遠程查看出現問題的客戶,發現問題並不是必然出現,而是偶然幾次,之后再次輸入密碼就可以正常登錄了。
最后發現原來是今年2月份chrome瀏覽器的cookies政策有改動,導致某些版本瀏覽器無法成功寫入cookies導致的。下面鏈接是我找到的解決方案,老外寫的,供參考。
https://www.thinktecture.com/en/identity/samesite/prepare-your-identityserver/
排查過程
首先觀察了請求的流程
上圖右邊的第一個請求就是登陸接口,這里登陸返回的是成功的,然后會跳轉到主頁,然后主頁面通過/connect/authorize來驗證用戶相關權限。
不過驗證的過程,IdentityServer4卻返回了無權限,所以導致又回到了登錄頁面。這個過程在用戶的感知中就是點擊了登錄,也提示了登錄成功,可是過了一會,頁面還是停留在登錄頁。
然后看了下id4的判定用戶是否登錄的代碼,如下
他是通過UserSession來獲取用戶狀態的,這個UserSession有不同的實現模式,默認是下面的cookie-based的Session
然后看了下登錄失敗的瀏覽器cookies情況,如下
成功的情況應該是如下
idsrv和idsrv.session就是id4保存用戶登錄狀態的cookies,這里idsrv是維持長期登錄狀態的的cookies,哪怕用戶關掉瀏覽器,再次打開到公司主頁,也能通過這個cookie進行認證,idsrv.session是本次對話的登錄標識,是短期的登錄狀態標識,這里從Expires的時間也能看出來。
既然是cookie沒有成功寫入,那么自然是查看請求的返回值,是否正確的返回了set cookie
請求內容
正常的情況
失敗的請求內容
仔細對比了下,如下
成功情況
Set-Cookie: idsrv.session=8ae738c38e3cbd358452d0b6303960b7; path=/; secure
失敗情況
Set-Cookie: idsrv.session=e524bbd54edc80bf247ea69191e43df8; path=/; secure; samesite=none
idsrv的set請求也是差別也是如此,那么看來很可能就是samesite=none配置在某些瀏覽器會導致cookies無法正常寫入。
解決方案
所以在中間件中手動改變samesite屬性為lax即可。
services.Configure<CookiePolicyOptions>(options => { options.MinimumSameSitePolicy = SameSiteMode.Lax; options.OnAppendCookie = cookieContext => CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); options.OnDeleteCookie = cookieContext => CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); }); private static void CheckSameSite(HttpContext httpContext, CookieOptions options) { if (options.SameSite == SameSiteMode.None) { var userAgent = httpContext.Request.Headers["User-Agent"].ToString(); if (DisallowsSameSiteNone(userAgent)) { options.SameSite = SameSiteMode.Lax; } } }