IdentityServer4遷移至3.x版本注意問題詳解


前言

之前有一位購買我課程的童鞋利用最新的IdentityServer4版本即對應.NET Core 3.x,發布到生產環境在學習,結果出了一些問題,此前我並未過多關注IdentityServer4升級到3.x版本,所以在此做一個基本的總結,或許能對出現相同問題的童鞋能提供一點幫助。

IdentityServer4遷移至3.x版本問題

針對將.NET Core 2.x升級到3.x就不用再多講,請參看官方遷移文檔(https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.1&tabs=visual-studio),我們只介紹對於對於配置IdentityServer4方面的更改變化

.NET Core Identity

對於Identity里面的上下文【IdentityDbContext】需要額外下載包【Microsoft.AspNetCore.Identity.EntityFrameworkCore】

 OIDC配置

 針對如下客戶端OIDC的配置,需要下載包【Microsoft.AspNetCore.Authentication.OpenIdConnect】

授權中間件配置 

針對客戶端認證和授權配置,需要如下配置授權中間件(認證和授權無先后順序)

遷移類生成

我們知道在此之前對於遷移命名是包含在dotnet CLI里面,現已修改為通過單獨的包來進行,所以我們需要下載包【Microsoft.EntityFrameworkCore.Design】,否則將拋出如下異常

還有可能遇到命令行工具版本和當前.NET Core版本不一致的問題,通過如下命令進行更新

  //使用PowerShell或CMD命令更新

  //更新到指定版本1)dotnet tool update --global dotnet-ef --version 3.1.2

  //更新到最新版本2) dotnet tool update --global dotnet-ef

Cookie安全策略問題(划重點) 

在本地環境可能么有任何問題,但是到了生產環境,可能會拋出如下錯誤,我們是不是會一臉懵逼呢。

warn: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler[15]
'.AspNetCore.Correlation.oidc.x9I39lxuVXliU0_mOAEPEbZy_EPESHQQRvq7LPatX7rv7y_vQi-HKLIwqNacHM62AeKarJVmr_KvjAL7nSX6hdeR' cookie not found.
info: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler[4]
Error from RemoteAuthentication: Correlation failed..

這要從Cookie的出生故事說起,大約在20年前設計cookie時以及之后重新設計該cookie時,跨站點請求偽造(CSRF)攻擊和跟蹤用戶都不是什么大事,在cookie規范中說,如果為特定域設置了cookie,則瀏覽器發出的每個請求都會將其發送到該域,無論我們是否直接導航到該域,如果瀏覽器只是從該域加載資源(即圖像),向其發送POST請求或將其一部分嵌入到iframe中,但是還有一種情況,我們並不希望瀏覽器自動將用戶會話cookie發送到服務器,因為這將允許任何網站會執行腳本,該腳本在該用戶的上下文中對服務器執行請求,為避免這種情況,於2016年起草了SameSite cookie規范,它使我們可以更好地控制何時應發送和不應該發送cookie,設置cookie時,我們現在可以在瀏覽器將其添加到其中時為每個cookie明確指定,為此,它引入了當瀏覽器位於我們自己的域上時相同站點cookie的概念,以及當瀏覽器導航到另一個域但將請求發送到我們的域時跨站點cookie的概念,為了向后兼容,相同站點cookie的默認設置並不會更改以前的行為,若我們加入該新功能,需要將cookie顯式設置為SameSite = Lax或SameSite = Strict,以使其更加安全,這已在.NET Framework和所有常見的瀏覽器中實現,Lax表示將在初始導航時將cookie發送到服務器,Strict表示僅在我們已經在該域中時(即在初始導航之后發送第二個請求)才發送cookie。但是呢,這項新功能卻並沒有被廣泛采用(基於2019年3月Chrome的遙測數據,Chrome在全球范圍內處理的所有cookie中,只有0.1%使用了SameSite標志,Google為了實現推動該新功能的目標,他們決定更改世界上最常用的瀏覽器的默認設置:Chrome 80將需要新指定的設置SameSite = None來保持處理Cookie的舊方法,並且如果我們像建議的舊規范那樣省略SameSite字段的話,它將cookie與SameSite = Lax一起設置,請注意:僅當cookie也被標記為Secure並且需要HTTPS連接時,設置SameSite = None才有效,這里關於更多SameSite的信息就不再闡述。如果我們有一個單頁Web應用程序(SPA),該Web應用程序通過另一個域上托管的身份提供程序(例如IdentityServer 4中的Idp)進行身份驗證,並且該應用程序使用所謂的令牌刷新,則將會受到影響,登錄IdP時,它將為我們的用戶設置一個會話cookie,並且該cookie來自IdP域,在身份驗證流程結束時,來自不同域的應用程序將收到某種訪問令牌,這些令牌通常生命周期並不長,當該令牌過期時,應用程序將無法再訪問資源服務器(API),如果用戶每次都必須再次登錄,可想用戶體驗之差,為防止這種情況,我們可以使用刷新令牌,在這種情況下,應用程序將創建一個用戶不可見的iframe,然后在該iframe中再次啟動身份驗證過程, IdP的網站已加載到iframe中,並且如果瀏覽器通過IdP發送會話cookie,則會識別用戶並發出新令牌,現在,iframe位於應用程序域中托管的SPA中,其內容來自IdP域,這將被視為跨站點請求,因此,如果Cookie明確指出SameSite = None,則Chrome 80只會將該Cookie從iframe發送到IdP,否則,令牌刷新將在Chrome 80中出現中斷的情況。也還有其他可能潛在的問題,如果我們在Web應用程序或網站中嵌入了來自另一個域的元素(例如視頻),並且這些元素需要Cookie才能正常運行(例如自動播放設置),那么這些也會需要設置SameSite策略,如果我們的應用程序需要從瀏覽器請求依賴Cookie身份驗證的第三方API,則同樣適用,我們只能更改自己服務器從而設置cookie行為。

 

講解了這么多貌似好像沒有用的廢話,實際上就是出現了跨站點安全策略即SameSite的設定,如上異常的拋出,追本溯源在於是什么原因導致了客戶端的Cookie丟失?通過上述對Cookie的講解,我們可以顯式設置SameSite安全策略從而保證到底發不發送Cookie,所以我猜測在.NET Core 3.x中是不是更改了Cookie的安全策略,如果客戶端的為Strict的話,那就會導致上述異常的發生,比如如下:

說到這里,為了驗證我的結論,我立馬翻看了關於.NET Core中Cookie對於安全策略的設置,難道真的將Strict作為默認的安全策略嗎?

 

原來該安全策略的默認選項就是Lax(寬松策略),然后繼續來到上述的issue(https://github.com/aspnet/Security/issues/1231),在2.0中就解決了此問題將Strict修改為了Lax,就是為了解決OAuth中重定向跳轉認證的問題。這個結果雖在意料之中,但是也在意料之外,那位童鞋也遇到了拋出上述異常的問題,我就是顯式設置上述安全策略為Lax得到了解決,讓我很是納悶,這是何故,我也不知道,但是確確實實是解決了,最終客戶端也正常跑起來了,真是(捂臉)的表情。最后也同樣重要的是,IdentityServer4在生產環境中是啟用了HTTPS,所以在發布到生產環境后若未使用HTTPS,一定要將啟用HTTPS選項顯式配置為false,而本地則不然,遇到問題首先分析問題,然后看官方文檔,如若還不能解決,只能通過經驗來進行可能原因分析了。

總結

本節我只是將IdentityServer4升級到.NET Core 3.x的版本需要注意的問題做了一個粗略的解答,根據我的經驗,一部分原因出在對於官方文檔概念未詳細解導致,另外一部分原因出在由於版本升級導致內置處理出現了更改,但官方文檔並未更新,這個最麻煩,出現這樣的問題只能硬啃源代碼並調試,我也同時將我原先在長沙社區成立時所演講的IDS4 Demo已更新到了最新.NET Core 3.1.2版本(https://github.com/wangpengxpy/IdentityServer4Sample)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM