介紹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驗證.
純屬個人理解,能力有限,有問題,請指正,謝謝