1. 程式人生 > >.Net Core 認證系統之基於Identity Server4 Token的JwtToken認證原始碼解析

.Net Core 認證系統之基於Identity Server4 Token的JwtToken認證原始碼解析

介紹JwtToken認證之前,必須要掌握.Net Core認證系統的核心原理,如果你還不瞭解,請參考.Net Core 認證元件原始碼解析,且必須對jwt有基本的瞭解,如果不知道,請百度.最重要的是你還需要掌握identity server4的基本用法,關於identity server4因為設計到兩個協議Oath2.0和openid connect協議,內容較多,不是本文重點,後續有時間我會寫一片關於identity server4的原始碼分析.且為了保證整個系統的高度可控,我重寫了整個id4,留下了password模式.如果有興趣,可以關注本人的後續文章.

假設你已經掌握以上內容,那麼整個流程可以抽象為如下步驟:

(1)、使用者輸入使用者名稱密碼同時帶著客戶端Id和客戶端金鑰去identity server4請求access token.(訪問令牌,令牌中帶著使用者Id,帶著客戶端的名稱和密碼)

(2)、拿到token後,接著使用者去請求客戶端指定的控制器方法,那麼客戶端第一步,會解析token中的客戶端名稱和密碼是否正確,還有過期時間等常規欄位的判斷.

(3)、token驗證通過,這個時候就可以拿到使用者資訊(ClaimsPrincipal)

(4)、此時我們拿到持有的使用者資訊中的使用者Id,發起httpclient或者grpc呼叫,去統一許可權系統查詢使用者的許可權是否有當前請求的方法,有就通過授權認證,返回資料,沒有,就返回許可權不足.

 

整個流程大致如上,本文的重點是當拿到id4頒發的有效令牌(token)後,客戶端如何解析?

微軟提供了IdentityServer4.AccessTokenValidation類庫,用來解析id4頒發的token.

.Net Core啟用IdentityServer4token驗證的方法如下:

 

指定id4的認證方案,並指定認證引數,那麼看看裡面到底幹了什麼

 因為id4的令牌有訪問令牌和引用令牌之分,但是password模式,只支援訪問令牌,所以

 

 這兩塊這裡就不分析了,如果你的專案用到了引用令牌.那麼自行查閱程式碼.

ok,回到第一行程式碼

 很明顯添加了JwtBearer的認證方案.所以IdentityServer4.AccessTokenValidation類庫是基於

回到.Net Core JwtBear認證的原始碼如下:

 很簡單,添加了方案名稱為Bearer IdentityServerAuthenticationJwt的認證方案,且處理器為JwtBearerHandler,並指定引數.如果你已經掌握.Net Core的核心認證元件的流程,那麼啥都不用說,直接看JwtBearerHandler幹了什麼,檢視核心的認證方法HandleAuthenticateAsync,原始碼如下:

 第一步,生成上下文,執行通過JwtBearerOptions引數註冊的MessageReceived事件,原始碼如下:

 所以,在token認證前,可以隨意操作上下文,微軟提示,給當前應用一個機會去拒絕一部分token。當然很明顯,你可以幹除了拒絕之外的很多事情.

接著

 檢查http head頭中的token是否合法,條件程式碼中也給出了.必須以Bearer開頭等

接下來,這段程式碼就很有趣了,如果你不瞭解identity Server4,你肯定無法下手.

 核心物件

 這個物件在IdentityModel類庫中有,但是這裡不介紹了

協議層面的東東,所以可以自行查詢原始碼.

接著回到JwtBearer認證的入口

 為啥要注入JwtBearerPostConfigureOptions這個配置物件呢?且這個配置物件是幹嘛的呢?關於PostConfigureOpetions是.Net Core核心配置系統裡面的一類物件,這類物件會在Options執行完畢之後執行,類似ABP模組載入系統的生命週期管理,執行完Init之後執行Post裡面的方法,這裡本質也是如此.ok,看看這個配置幹了什麼,原始碼如下:

 

 到這裡一目瞭然.ConfigurationManager實際就是去遠端呼叫文件配置(本質是去拿給token前面的rsa檔案,來給token解密,並驗證token的有效性)用的.

 呼叫的是id4的文件配置,但是我為了減少不必要的遠端呼叫,拿掉了id4的文件發現TokenPoint.改用在客戶端直接配置ras檔案,來給token解密,這裡因為我用的是password模式,所有的系統都是高度信任的.所以可以這樣做.而且微軟也考慮到了這一點,程式碼如下:

 你可以跳過遠端呼叫,而改用本地直接配置.引數在JwtBearerOptions的TokenValidationParameters屬性中配置.

這個時候你已經通過本地配置,或者通過呼叫id4的文件發現TokenPoint拿到了給token簽名的rsa檔案,接著

 

 

 呼叫JwtBearerOptions配置引數中的SecurityTokenValidators,原始碼如下:

 本質就是呼叫JwtSecurityTokenHandler去驗證token的內容是否有效,並解析出使用者資訊,原始碼如下:

 並返回認證結果.

所以整個核心認證流程如下:

1、拿到http請求上下文中的token

2、執行一系列事件

3、遠端呼叫id4文件發現服務拿到簽名rsa檔案或者本地指定rsa檔案

4、用私鑰解密token,判斷其有效性

5、執行一系列事件

6、返回使用者認證結果

整個核心的流程可以抽象出如下程式碼:

 此時就拿到可以訪問的token,裡面包含使用者Id的資訊,接著配合授權系統的動態授權功能,去許可權系統判斷當前使用者是否具有訪問當前Api的許可權.就能判斷當前請求是否被允許

這裡只介紹了id4 token的核心認證流程,一些細節點,比如token的有效性校驗,就有很多內容沒介紹.不明白,可以在下面提問.

 

注意:如果你和我一樣重寫了id4,同時你拿掉了文件發現tokenPoint,那麼就不能用IdentityServer4.AccessTokenValidation元件了(我暫時沒找到,我覺得也沒必要,直接自己寫了),只能使用JwtBear認證元件,再參考

IdentityServer4.AccessTokenValidation元件中的IdentityServerAuthenticationOptions引數中的ConfigureJwtBearer方法指定JwtBear必須的認證引數,來實現自定以的Id4token驗證.

純屬個人理解,能力有限,有問題,請指正,謝謝

&n