一、前言
在IdentityServer4中有兩種令牌,一個是JWT和Reference Token,在IDS4中預設用的是JWT,那麼這兩者有什麼差別呢?
二、JWT與Reference Token的差別
1、JWT(不可撤回)
JWT是一個非常輕巧的規範,一般被用來在身份提供者和服務提供者間傳遞安全可靠的資訊。JWT令牌是一個自包含的通路令牌 - 它是一個帶有聲明和過期的受保護資料結構。一旦API了解了密鑰材料,它就可以驗證自包含的令牌,而無需與發行者進行通信。這使得JWT難以撤銷。它們将一直有效,直到它們過期。
JWT常被用于前後端分離,可以和 Restful API 配合使用,常用于建構身份認證機制,一個 JWT 實際上就是一個字元串,它包含了使用.分隔的三部分: Header 頭部 Payload 負載 Signature 簽名(格式:Header.Payload.Signature)
在這個三個部分中最關鍵的就是signature。
signature:被用來确認JWT資訊的發送者是誰,并保證資訊沒有被篡改,使用header中指定的算法将編碼後的header、編碼後的payload、一個secret進行加密。是以簽名算法推薦使用RSA或ECDSA非對稱加密算法。
JWT特點:
A、JWT 預設是不加密,但也是可以加密的。生成原始 Token 以後,可以用密鑰再加密一次。
B、為了減少盜用,JWT 不應該使用 HTTP 協定明碼傳輸,要使用 HTTPS 協定傳輸
C、jwt去中心化的思想:api資源收到第一個請求之後,會去id4伺服器擷取公鑰,然後用公鑰驗證token是否合法,如果合法進行後面的有效性驗證。有且隻有第一個請求才會去id4伺服器請求公鑰,後面的請求都會用第一次請求的公鑰來驗證,這也是jwt去中心化驗證的思想。(注:如果簽名證書發生改變則需要重新開機有請求ids4伺服器的資源伺服器。)
D、JWT 本身包含了認證資訊,一旦洩露,任何人都可以獲得該令牌的所有權限。為了減少盜用,JWT 的有效期應該設定得比較短。對于一些比較重要的權限,使用時應該再次對使用者進行認證。
2、Reference Token(不攜帶任何使用者資料,可撤回)
當使用 Reference token 的時候,服務端會對 Token 進行持久化,當用戶端請求資源端(API)的時候,資源端需要每次都去服務端通信去驗證 Token 的合法性[/connect/introspect],IdentityServer4.AccessTokenValidation 中間件中可以配置緩存一定的時候去驗證,并且 Token 是支援撤銷[/connect/revocation]的。
使用引用令牌時 - IdentityServer會将令牌的内容存儲在資料存儲中,并且隻會将此令牌的唯一辨別符發回給用戶端。接收此引用的API必須打開與IdentityServer的反向通道通信以驗證令牌。如下:access_token就是唯一辨別。(注不攜帶任何資料)
當 AccessTokenType 定義為 Reference 的時候,驗證資源端要注意配置 ApiSecrets 以確定 POST /connect/introspect HTTP/1.1 接口能驗證通過,當 AccessTokenType 定義為 Jwt 的時候則資源端可不配置 options.ApiSecret 選項。如下圖:
Reference Token官方圖如下:
以上就是JWT與Reference token的差別。為了減少通路中心伺服器的資源,使用JWT還是非常棒的,畢竟與伺服器互動的資源還是非常的昂貴的。不過具體的還得視實際情況而定。
那麼我們來看一下在IDS4中API使用JWT以及Reference Token的互動流程圖
三、IDS4中API使用JWT以及Reference Token與認證中心的互動流程圖
此圖為:JWT,當然大家可以通過fiddler 抓包工具來檢視一下具體的資料流就能明白其中的道理。
注:資源伺服器在第一次解析AccessToken的時候會先到授權伺服器擷取配置資料(例如會通路:http://localhost:5000/.well-known/openid-configuration 擷取配置的,http://localhost:5000/.well-known/openid-configuration/jwks 擷取jwks)),之後解析AccessToken都會使用第一次擷取到的配置資料,是以如果授權服務的配置更改了(加密證書等等修改了),那麼應該重新開機資源伺服器使之重新擷取新的配置資料;
此圖為:Reference Token
以上即JWT與Reference Token 流程圖。
四、JWT中使用RSA加密
在說明JWT使用RSA加密之前我們先來比較一下其他的加密算法
1、HS256與RS256的差別
HS256 使用密鑰生成固定的簽名,RS256 使用成非對稱進行簽名。簡單地說,HS256 必須與任何想要驗證 JWT的 用戶端或 API 共享秘密。即 如下圖
RS256 生成非對稱簽名,這意味着必須使用私鑰來簽簽名 JWT,并且必須使用對應的公鑰來驗證簽名。與對稱算法不同,使用 RS256 可以保證服務端是 JWT 的簽名者,因為服務端是唯一擁有私鑰的一方。這樣做将不再需要在許多應用程式之間共享私鑰
2、建立自簽名證書(操作步驟)
生産環境(負載叢集)一般需要使用固定的證書簽名與驗簽,以確定重新開機服務端或負載的時候 Token 都能驗簽通過。(不使用臨時證書)
那麼證書如何生成請看下面分解步驟:
第一種:使用OpenSSL生成證書,注:RSA加密證書長度要2048以上,否則服務運作會抛異常
#Linux系統生成證書:(推薦使用)
sudo yum install openssl (CentOS)
#生成私鑰檔案
openssl genrsa -out idsrv4.key 2048
#建立證書簽名請求檔案 CSR(Certificate Signing Request),用于送出給證書頒發機構(即 Certification Authority (CA))即對證書簽名,申請一個數字證書。
openssl req -new -key idsrv4.key -out idsrv4.csr
#生成自簽名證書(證書頒發機構(CA)簽名後的證書,因為自己做測試那麼證書的申請機構和頒發機構都是自己,crt 證書包含持有人的資訊,持有人的公鑰,以及簽署者的簽名等資訊。當使用者安裝了證書之後,便意味着信任了這份證書,同時擁有了其中的公鑰。)
openssl x509 -req -days 365 -in idsrv4.csr -signkey idsrv4.key -out idsrv4.crt (包含公鑰)
#自簽名證書與私匙合并成一個檔案(注:.pfx中可以加密碼保護,是以相對安全些)
openssl pkcs12 -export -in idsrv4.crt -inkey idsrv4.key -out idsrv4.pfx (注:在生成的過程中會讓我們輸入Export Password)
證書截圖如下:
第二種:
openssl req -newkey rsa:2048 -nodes -keyout idsrv4.key -x509 -days 365 -out idsrv4.cer
openssl pkcs12 -export -in idsrv4.cer -inkey idsrv4.key -out idsrv4.pfx
生成如下:
3、證書生成之後就可進入VS2017中配置
拷貝生成的證書,放到認證/授權伺服器項目中。(VS中配置檔案設定檔案始終複制),最後把證書路徑和密碼配置到 IdentityServer 中,因為我們自簽名的證書是 PKCS12 (個人數字證書标準,Public Key Cryptography Standards #12) 标準包含私鑰與公鑰)标準,包含了公鑰和私鑰。
A、在appsetting.json 配置檔案中添加如下:此處需要配置password,自定義即可。
B、在starup.cs中ConfigureServices方法中配置如下即可。
配置完後即可。我們啟動IDS4項目即可生成加密的token。
将得到的token在jwt.io 網站來認證一下:把字尾為 crt 公鑰、key私鑰複制到驗證中,發現認證ok。這樣即可實作防篡改。
五、總結
在實際環境中應該使用加密的token,而不應該使用臨時令牌。以及盡量設定token的過期時間短,以及重新整理token的機制,這樣可以盡可能的保護token以及資料安全。
asp.net core 交流群:787464275 歡迎加群交流
如果您認為這篇文章還不錯或者有所收獲,您可以點選右下角的【推薦】按鈕精神支援,因為這種支援是我繼續寫作,分享的最大動力!
作者:
LouieGuo http://www.cnblogs.com/stulzq聲明:原創部落格請在轉載時保留原文連結或者在文章開頭加上本人部落格位址,如發現錯誤,歡迎批評指正。凡是轉載于本人的文章,不能設定打賞功能,如有特殊需求請與本人聯系!
微信公衆号:歡迎關注 QQ技術交流群: 歡迎加群