JWT
在了解jwt之前,先了解一下常用的會話管理
- 基于
的管理方式server-session
-
的管理方式cookie-based
-
的管理方式token-based
一.基于
server-session
的管理
- 服務端
是使用者第一次通路應用時,伺服器就會建立的對象,代表使用者的一次會話過程,伺服器為每一個session
都配置設定一個唯一的session
,以保證每個使用者都有一個不同的sessionid
對象。session
- 伺服器在建立完
後,會把session
通過sessionid
傳回給使用者所在的浏覽器,這樣當使用者第二次及以後向伺服器發送請求的時候,就會通過cookie
把cookie
傳回給伺服器,以便伺服器能夠根據sessionid
找到與該使用者對應的sessionid
對象。session
-
通常有失效時間的設定,比如2個小時。當失效時間到,伺服器會銷毀之前的session
,并建立新的session
傳回給使用者。但是隻要使用者在失效時間内,有發送新的請求給伺服器,通常伺服器都會把他對應的session
的失效時間根據目前的請求時間再延長2個小時。session
-
在一開始并不具備會話管理的作用。它隻有在使用者登入認證成功之後,并且往session
對象裡面放入了使用者登入成功的憑證,才能用來管理會話。管理會話的邏輯也很簡單,隻要拿到使用者的session
對象,看它裡面有沒有登入成功的憑證,就能判斷這個使用者是否已經登入。當使用者主動退出的時候,會把它的session
對象裡的登入憑證清掉。是以在使用者登入前或退出後或者session
對象失效時,肯定都是拿不到需要的登入憑證的。session
以上過程可簡單使用流程圖描述如下:

它還有一個比較大的優點就是安全性好,因為在浏覽器端與伺服器端保持會話狀态的媒介始終隻是一個
sessionid
串,隻要這個串夠随機,攻擊者就不能輕易冒充他人的
sessionid
進行操作;除非通過CSRF或http劫持的方式,才有可能冒充别人進行操作;即使冒充成功,也必須被冒充的使用者
session
裡面包含有效的登入憑證才行。但是在真正決定用它管理會話之前,也得根據自己的應用情況考慮以下幾個問題:
- 這種方式将會話資訊存儲在web伺服器裡面,是以在使用者同時線上量比較多時,這些會話資訊會占據比較多的記憶體;
- 當應用采用叢集部署的時候,會遇到多台web伺服器之間如何做
共享的問題。因為session
是由單個伺服器建立的,但是處理使用者請求的伺服器不一定是那個建立session
的伺服器,這樣他就拿不到之前已經放入到session
中的登入憑證之類的資訊了;session
- 多個應用要共享
時,除了以上問題,還會遇到跨域問題,因為不同的應用可能部署的主機不一樣,需要在各個應用做好session
跨域的處理。cookie
針對問題1和問題2,我見過的解決方案是采用
redis
這種中間伺服器來管理
session
的增删改查,一來減輕web伺服器的負擔,二來解決不同web伺服器共享
session
的問題。針對問題3,由于服務端的
session
依賴
cookie
來傳遞
sessionid
,是以在實際項目中,隻要解決各個項目裡面如何實作
sessionid
的
cookie
跨域通路即可,這個是可以實作的,就是比較麻煩,前後端有可能都要做處理。
二.
cookie-based
的管理方式
由于前一種方式會增加伺服器的負擔和架構的複雜性,是以後來就有人想出直接把使用者的登入憑證直接存到用戶端的方案,當使用者登入成功之後,把登入憑證寫到
cookie
裡面,并給
cookie
設定有效期,後續請求直接驗證存有登入憑證的
cookie
是否存在以及憑證是否有效,即可判斷使用者的登入狀态。使用它來實作會話管理的整體流程如下:
- 使用者發起登入請求,服務端根據傳入的使用者密碼之類的身份資訊,驗證使用者是否滿足登入條件,如果滿足,就根據使用者資訊建立一個登入憑證,這個登入憑證簡單來說就是一個對象,最簡單的形式可以隻包含使用者
,憑證建立時間和過期時間三個值。id
- 服務端把上一步建立好的登入憑證,先對它做數字簽名,然後再用對稱加密算法做加密處理,将簽名、加密後的字串,寫入
。cookie
的名字必須固定(如cookie
),因為後面再擷取的時候,還得根據這個名字來擷取ticket
值。這一步添加數字簽名的目的是防止登入憑證裡的資訊被篡改,因為一旦資訊被篡改,那麼下一步做簽名驗證的時候肯定會失敗。做加密的目的,是防止cookie
被别人截取的時候,無法輕易讀到其中的使用者資訊。cookie
- 使用者登入後發起後續請求,服務端根據上一步存登入憑證的
名字,擷取到相關的cookie
值。然後先做解密處理,再做數字簽名的認證,如果這兩步都失敗,說明這個登入憑證非法;如果這兩步成功,接着就可以拿到原始存入的登入憑證了。然後用這個憑證的過期時間和目前時間做對比,判斷憑證是否過期,如果過期,就需要使用者再重新登入;如果未過期,則允許請求繼續。cookie
這種方式最大的優點就是實作了服務端的無狀态化,徹底移除了服務端對會話的管理的邏輯,服務端隻需要負責建立和驗證登入
cookie
即可,無需保持使用者的狀态資訊。對于第一種方式的第二個問題,使用者會話資訊共享的問題,它也能很好解決:因為如果隻是同一個應用做叢集部署,由于驗證登入憑證的代碼都是一樣的,是以不管是哪個伺服器處理使用者請求,總能拿到
cookie
中的登入憑證來進行驗證;如果是不同的應用,隻要每個應用都包含相同的登入邏輯,那麼他們也是能輕易實作會話共享的,不過這種情況下,登入邏輯裡面數字簽名以及加密解密要用到的密鑰檔案或者密鑰串,需要在不同的應用裡面共享,總而言之,就是需要算法完全保持一緻。
這種方式由于把登入憑證直接存放用戶端,并且需要
cookie
傳來傳去,是以它的缺點也比較明顯:
-
有大小限制,存儲不了太多資料,是以要是登入憑證存的消息過多,導緻加密簽名後的串太長,就會引發别的問題,比如其它業務場景需要cookie
的時候,就有可能沒那麼多空間可用了;是以用的時候得謹慎,得觀察實際的登入cookie
的大小;比如太長,就要考慮是非是數字簽名的算法太嚴格,導緻簽名後的串太長,那就适當調整簽名邏輯;比如如果一開始用4096位的RSA算法做數字簽名,可以考慮換成1024、2048位;cookie
- 每次傳送
,增加了請求的數量,對通路性能也有影響;cookie
- 也有跨域問題,畢竟還是要用
。cookie
前面兩種會話管理方式因為都用到
cookie
,不适合用在native app裡面:native app不好管理
cookie
,畢竟它不是浏覽器。這兩種方案都不适合用來做純api服務的登入認證。要實作api服務的登入認證,就要考慮下面要介紹的第三種會話管理方式。
三.
token-based
的管理方式
這種方式從流程和實作上來說,跟
cookie-based
的方式沒有太多差別,隻不過
cookie-based
裡面寫到
cookie
裡面的
ticket
在這種方式下稱為
token
,這個
token
在傳回給用戶端之後,後續請求都必須通過url參數或者是http header的形式,主動帶上
token
,這樣服務端接收到請求之後就能直接從http header或者url裡面取到token進行驗證:
這種方式不通過
cookie
進行
token
的傳遞,而是每次請求的時候,主動把
token
加到http header裡面或者url後面,是以即使在native app裡面也能使用它來調用我們通過web釋出的api接口。app裡面還要做兩件事情:
- 有效存儲
,得保證每次調接口的時候都能從同一個位置拿到同一個token
;token
- 每次調接口的的代碼裡都得把
加到header或者接口位址裡面。token
看起來麻煩,其實也不麻煩,這兩件事情,對于app來說,很容易做到,隻要對接口調用的子產品稍加封裝即可。
這種方式同樣适用于網頁應用,
token
可以存于
localStorage
或者
sessionStorage
裡面,然後每發ajax請求的時候,都把
token
拿出來放到ajax請求的header裡即可。不過如果是非接口的請求,比如直接通過點選連結請求一個頁面這種,是無法自動帶上
token
的。是以這種方式也僅限于走純接口的web應用。
這種方式用在web應用裡也有跨域的問題,比如應用如果部署在a.com,api服務部署在b.com,從a.com裡面發出ajax請求到b.com,預設情況下是會報跨域錯誤的,這種問題可以用CORS(跨域資源共享)的方式來快速解決。
這種方式跟
cookie-based
的方式同樣都還有的一個問題就是
ticket
或者
token
重新整理的問題。有的産品裡面,你肯定不希望使用者登入後,操作了半個小時,結果
ticket
或者
token
到了過期時間,然後使用者又得去重新登入的情況出現。這個時候就得考慮
ticket
或
token
的自動重新整理的問題,簡單來說,可以在驗證
ticket
或
token
有效之後,自動把
ticket
或
token
的失效時間延長,然後把它再傳回給用戶端;用戶端如果檢測到伺服器有傳回新的
ticket
或
token
,就替換原來的
ticket
或
token
。
四. 安全問題
在web應用裡面,會話管理的安全性始終是最重要的安全問題,這個對使用者的影響極大。
首先從會話管理憑證來說,第一種方式的會話憑證僅僅是一個
sessionid
,是以隻要這個
sessionid
足夠随機,而不是一個自增的數字id值,那麼其它人就不可能輕易地冒充别人的
sessionid
進行操作;第二種方式的憑證
ticket
以及第三種方式的憑證
token
都是一個在服務端做了數字簽名,和加密處理的串,是以隻要密鑰不洩露,别人也無法輕易地拿到這個串中的有效資訊并對它進行篡改。總之,這三種會話管理方式的憑證本身是比較安全的。
然後從用戶端和服務端的http過程來說,當别人截獲到用戶端請求中的會話憑證,就能拿這個憑證冒充原使用者,做一些非法操作,而伺服器也認不出來。這種安全問題,可以簡單采用https來解決,雖然可能還有http劫持這種更高程度的威脅存在,但是我們從代碼能做的防範,确實也就是這個層次了。
JWT介紹 (https://jwt.io/)
JSON Web Token(JWT)
是一個開放标準(RFC 7519),它定義了一種緊湊和自包含的方式,用于在各方之間作為JSON對象安全地傳輸資訊。作為标準,它沒有提供技術實作,但是大部分的語言平台都有按照它規定的内容提供了自己的技術實作,是以實際在用的時候,隻要根據自己目前項目的技術平台,到官網上選用合适的實作庫即可。
使用
JWT
來傳輸資料,實際上傳輸的是一個字元串,這個字元串就是所謂的json web token字元串。是以廣義上,
JWT
是一個标準的名稱;狹義上,
JWT
指的就是用來傳遞的那個
token
字元串。這個串有兩個特點:
1. 緊湊:指的是這個串很小,能通過url 參數,http請求送出的資料以及http header的方式來傳遞;
2. 自包含:這個串可以包含很多資訊,比如使用者的id、角色等,别人拿到這個串,就能拿到這些關鍵的業務資訊,進而避免再通過資料庫查詢等方式才能得到它們。
通常一個
JWT
是長這個樣子的:
要知道一個
JWT
是怎麼産生以及如何用于會話管理,隻要弄清楚
JWT
的資料結構以及它簽發和驗證的過程即可。
一.
JWT
的資料結構以及簽發過程
一個
JWT
實際上是由三個部分組成:
header(頭部)
、
payload(載荷)
和
signature(簽名
)。這三個部分在
JWT
裡面分别對應英文句号分隔出來的三個串:
先來看
header
部分的結構以及它的生成方法。
header
部分是由下面格式的json結構生成出來:
這個json中的
typ
屬性,用來辨別整個
token
字元串是一個
JWT
字元串;它的
alg
屬性,用來說明這個
JWT
簽發的時候所使用的簽名和摘要算法,常用的值以及對應的算法如下:
typ
跟
alg
屬性的全稱其實是
type
跟
algorithm
,分别是類型跟算法的意思。之是以都用三個字母來表示,也是基于
JWT
最終字串大小的考慮,同時也是跟
JWT
這個名稱保持一緻,這樣就都是三個字元了…
typ
跟
alg
是
JWT
中标準中規定的屬性名稱,雖然在簽發
JWT
的時候,也可以把這兩個名稱換掉,但是如果随意更換了這個名稱,就有可能在
JWT
驗證的時候碰到問題,因為拿到
JWT
的人,預設會根據
typ
和
alg
去拿
JWT
中的
header
資訊,當你改了名稱之後,顯然别人是拿不到
header
資訊的,他又不知道你把這兩個名字換成了什麼。
JWT
作為标準的意義在于統一各方對同一個事情的處理方式,各個使用方都按它約定好的格式和方法來簽發和驗證
token
,這樣即使運作的平台不一樣,也能夠保證
token
進行正确的傳遞。
一般簽發
JWT
的時候,
header
對應的json結構隻需要
typ
和
alg
屬性就夠了。
JWT
的
header
部分是把前面的json結構,經過Base64Url編碼之後生成出來的:
(線上base64編碼:http://www1.tc711.com/tool/BASE64.htm)
再來看
payload
部分的結構和生成過程。
payload
部分是由下面類似格式的json結構生成出來:
payload
的json結構并不像
header
那麼簡單,
payload
用來承載要傳遞的資料,它的json結構實際上是對
JWT
要傳遞的資料的一組聲明,這些聲明被
JWT
标準稱為
claims
,它的一個“屬性值對”其實就是一個
claim
,每一個
claim
的都代表特定的含義和作用。比如上面結構中的
sub
代表這個
token
的所有人,存儲的是所有人的
ID
;
name
表示這個所有人的名字;
admin
表示所有人是否管理者的角色。當後面對
JWT
進行驗證的時候,這些
claim
都能發揮特定的作用。
根據
JWT
的标準,這些
claims
可以分為以下三種類型:
1.
Reserved claims(保留)
,它的含義就像是程式設計語言的保留字一樣,屬于
JWT
标準裡面規定的一些
claim
。
JWT
标準裡面定好的
claim
有:
iss(Issuser)
:代表這個JWT的簽發主體;
sub(Subject)
:代表這個JWT的主體,即它的所有人;
aud(Audience)
:代表這個JWT的接收對象;
exp(Expiration time)
:是一個時間戳,代表這個JWT的過期時間;
nbf(Not Before)
:是一個時間戳,代表這個JWT生效的開始時間,意味着在這個時間之前驗證JWT是會失敗的;
iat(Issued at)
:是一個時間戳,代表這個JWT的簽發時間;
jti(JWT ID)
:是JWT的唯一辨別。
-
,略(不重要)Public claims
-
,這個指的就是自定義的Private claims
。比如前面那個結構舉例中的claim
和admin
都屬于自定的name
。這些claim
跟claim
标準規定的JWT
差別在于:claim
規定的JWT
,claim
的接收方在拿到JWT
之後,都知道怎麼對這些标準的JWT
進行驗證;而claim
不會驗證,除非明确告訴接收方要對這些claim進行驗證以及規則才行。private claims
按照
JWT
标準的說明:保留的
claims
都是可選的,在生成
payload
不強制用上面的那些
claim
,你可以完全按照自己的想法來定義
payload
的結構,不過這樣搞根本沒必要:第一是,如果把
JWT
用于認證, 那麼
JWT
标準内規定的幾個
claim
就足夠用了,甚至隻需要其中一兩個就可以了,假如想往
JWT
裡多存一些使用者業務資訊,比如角色和使用者名等,這倒是用自定義的
claim
來添加;第二是,
JWT
标準裡面針對它自己規定的
claim
都提供了有詳細的驗證規則描述,每個實作庫都會參照這個描述來提供
JWT
的驗證實作,是以如果是自定義的
claim
名稱,那麼你用到的實作庫就不會主動去驗證這些
claim
。
最後也是把這個json結構做base64url編碼之後,就能生成
payload
部分的串:
(線上base64編碼:http://www1.tc711.com/tool/BASE64.htm)
最後看
signature
部分的生成過程。簽名是把
header
和
payload
對應的json結構進行base64url編碼之後得到的兩個串用英文句點号拼接起來,然後根據
header
裡面
alg
指定的簽名算法生成出來的。算法不同,簽名結果不同,但是不同的算法最終要解決的問題是一樣的。以
alg: HS256
為例來說明前面的簽名如何來得到。按照前面
alg
可用值的說明,HS256其實包含的是兩種算法:HMAC算法和SHA256算法,前者用于生成摘要,後者用于對摘要進行數字簽名。這兩個算法也可以用HMACSHA256來統稱。運用HMACSHA256實作
signature
的算法是:
正好找到一個線上工具能夠測試這個簽名算法的結果,比如我們拿前面的
header
和
payload
串來測試,并把“secret”這個字元串就當成密鑰來測試:
(https://1024tools.com/hmac)
最後的結果B其實就是JWT需要的signature。不過對比我在介紹JWT的開始部分給出的JWT的舉例:
會發現通過線上工具生成的
header
與
payload
都與這個舉例中的對應部分相同,但是通過線上工具生成的
signature
與上面圖中
的signature
有細微差別,在于最後是否有“=”字元。這個差別産生的原因在于上圖中的
JWT
是通過
JWT
的實作庫簽發的
JWT
,這些實作庫最後編碼的時候都用的是base64url編碼,而前面那些線上工具都是bas64編碼,這兩種編碼方式不完全相同,導緻編碼結果有差別。
以上就是一個
JWT
包含的全部内容以及它的簽發過程。接下來看看該如何去驗證一個
JWT
是否為一個有效的
JWT
。
二.
JWT
的驗證過程
這個部分介紹
JWT
的驗證規則,主要包括簽名驗證和
payload
裡面各個标準
claim
的驗證邏輯介紹。隻有驗證成功的
JWT
,才能當做有效的憑證來使用。
先說簽名驗證。當接收方接收到一個
JWT
的時候,首先要對這個
JWT
的完整性進行驗證,這個就是簽名認證。它驗證的方法其實很簡單,隻要把
header
做base64url解碼,就能知道
JWT
用的什麼算法做的簽名,然後用這個算法,再次用同樣的邏輯對
header
和
payload
做一次簽名,并比較這個簽名是否與
JWT
本身包含的第三個部分的串是否完全相同,隻要不同,就可以認為這個
JWT
是一個被篡改過的串,自然就屬于驗證失敗了。接收方生成簽名的時候必須使用跟
JWT
發送方相同的密鑰,意味着要做好密鑰的安全傳遞或共享。
再來看
payload
的
claim
驗證,拿前面标準的
claim
來一一說明:
iss(Issuser)
:如果簽發的時候這個
claim
的值是“a.com”,驗證的時候如果這個
claim
的值不是“a.com”就屬于驗證失敗;
sub(Subject)
:如果簽發的時候這個
claim
的值是“liuyunzhuge”,驗證的時候如果這個
claim
的值不是“liuyunzhuge”就屬于驗證失敗;
(Audience)
:如果簽發的時候這個
claim
的值是“[‘b.com’,’c.com’]”,驗證的時候這個
claim
的值至少要包含b.com,c.com的其中一個才能驗證通過;
exp(Expiration time)
:如果驗證的時候超過了這個
claim
指定的時間,就屬于驗證失敗;
nbf(Not Before)
:如果驗證的時候小于這個
claim
指定的時間,就屬于驗證失敗;
iat(Issued at)
:它可以用來做一些maxAge之類的驗證,假如驗證時間與這個
claim
指定的時間相差的時間大于通過maxAge指定的一個值,就屬于驗證失敗;
jti(JWT ID)
:如果簽發的時候這個
claim
的值是“1”,驗證的時候如果這個
claim
的值不是“1”就屬于驗證失敗;
需要注意的是,在驗證一個
JWT
的時候,簽名認證是每個實作庫都會自動做的,但是
payload
的認證是由使用者來決定的。因為
JWT
裡面可能不會包含任何一個标準的
claim
,是以它不會自動去驗證這些
claim
。
以登入認證來說,在簽發
JWT
的時候,完全可以隻用
sub
跟
exp
兩個
claim
,用
sub
存儲使用者的
id
,用
exp
存儲它本次登入之後的過期時間,然後在驗證的時候僅驗證
exp
這個
claim
,以實作會話的有效期管理。
JWT SSO
場景一:使用者發起對業務系統的第一次通路,假設他第一次通路的是系統A的some/page這個頁面,它最終成功通路到這個頁面的過程是:
在這個過程裡面,我認為了解的關鍵點在于:
- 它用到了兩個
(cookie
和jwt
)和三次重定向來完成會話的建立和會話的傳遞;sid
-
的jwt
是寫在systemA.com這個域下的,是以每次重定向到systemA.com的時候,cookie
這個jwt
隻要有就會帶過去;cookie
-
的sid
是寫在cas.com這個域下的,是以每次重定向到cas.com的時候,cookie
這個sid
隻要有就會帶過去;cookie
- 在驗證
jwt
的時候,如何知道目前使用者已經建立了sso的會話?
因為
的jwt
裡面存儲了之前建立的sso會話的payload
,是以當cas拿到sessionid
,就相當于拿到了jwt
,然後用這個sessionid
去判斷有沒有的對應的sessionid
對象即可。session
還要注意的是:CAS服務裡面的
session
屬于服務端建立的對象,是以要考慮
sessionid
唯一性以及
session
共享(假如CAS采用叢集部署的話)的問題。
sessionid
的唯一性可以通過使用者名密碼加随機數然後用hash算法如md5簡單處理;
session
共享,可以用
memcached
或者
redis
這種專門的支援叢集部署的緩存伺服器管理
session
來處理。
由于服務端
session
具有生命周期的特點,到期需自動銷毀,是以不要自己去寫
session
的管理,免得引發其它問題,到github裡找開源的緩存管理中間件來處理即可。存儲
session
對象的時候,隻要用
sessionid
作為key,
session
對象本身作為
value
,存入緩存即可。
session
對象裡面除了
sessionid
,還可以存放登入之後擷取的使用者資訊等業務資料,友善業務系統調用的時候,從
session
裡面傳回會話資料。
場景二:使用者登入之後,繼續通路系統A的其它頁面,如some/page2,它的處理過程是:
從這一步可以看出,即使登入之後,也要每次跟CAS校驗
jwt
的有效性以及會話的有效性,其實
jwt
的有效性也可以放在業務系統裡面處理的,但是會話的有效性就必須到CAS那邊才能完成了。當CAS拿到
jwt
裡面的
sessionid
之後,就能到
session
緩存伺服器裡面去驗證該
sessionid
對應的
session
對象是否存在,不存在,就說明會話已經銷毀了(退出)。
場景三:使用者登入了系統A之後,再去通路其他系統如系統B的資源,比如系統B的some/page,它最終能通路到系統B的some/page的流程是:
這個過程的關鍵在于第一次重定向的時候,它會把
sid
這個
cookie
帶回給CAS伺服器,是以CAS伺服器能夠判斷出會話是否已經建立,如果已經建立就跳過登入頁的邏輯。
場景四:使用者繼續通路系統B的其它資源,如系統B的some/page2:
這個場景的邏輯跟場景二完全一緻。
場景五:登出,假如它從系統B發起退出,最終的流程是:
最重要的是要清除
sid
的
cookie
,
jwt
的
cookie
可能業務系統都有建立,是以不可能在退出的時候還挨個去清除那些系統的
cookie
,隻要
sid
一清除,那麼即使那些
jwt
的
cookie
在下次通路的時候還會被傳遞到業務系統的服務端,由于
jwt
裡面的
sid
已經無效,是以最後還是會被重定向到CAS登入頁進行處理。
方案總結
以上方案兩個關鍵的前提:
- 整個會話管理其實還是基于服務端的
來做的,隻不過這個session
隻存在于CAS服務裡面;session
- CAS之是以信任業務系統的
,是因為這個jwt
是CAS簽發的,理論上隻要認證通過,就可以認為這個jwt
是合法的。jwt
jwt
本身是不可僞造,不可篡改的,但是不代表非法使用者冒充正常用法發起請求,是以正常的幾個安全政策在實際項目中都應該使用:
- 使用https
- 使用http-only的
,針對cookie
和sid
jwt
- 管理好密鑰
- 防範CSRF攻擊。
尤其是CSRF攻擊形式,很多都是鑽代碼的漏洞發生的,是以一旦出現CSRF漏洞,并且被人利用,那麼别人就能用獲得的
jwt
,冒充正常使用者通路所有業務系統,這個安全問題的後果還是很嚴重的。考慮到這一點,為了在即使有漏洞的情況将損害減至最小,可以在
jwt
裡面加入一個系統辨別,添加一個驗證,隻有傳過來的
jwt
内的系統辨別與發起
jwt
驗證請求的服務一緻的情況下,才允許驗證通過。這樣的話,一個非法使用者拿到某個系統的
jwt
,就不能用來通路其它業務系統了。
在業務系統跟CAS發起attach/validate請求的時候,也可以在CAS端做些處理,因為這個請求,在一次SSO過程中,一個系統隻應該發一次,是以隻要之前已經給這個系統簽發過jwt了,那麼後續 同一系統的attach/validate請求都可以忽略掉。
總的來說,這個方案的好處有:
- 完全分布式,跨平台,CAS以及業務系統均可采用不同的語言來開發;
- 業務系統如系統A和系統B,可實作服務端無狀态
- 假如是自己來實作,那麼可以輕易的在CAS裡面內建使用者注冊服務以及第三方登入服務,如微信登入等。
它的缺陷是:
- 第一次登入某個系統,需要三次重定向;
- 登入後的後續請求,每次都需要跟CAS進行會話驗證,是以CAS的性能負載會比較大
- 登陸後的後續請求,每次都跟CAS互動,也會增加請求響應時間,影響使用者體驗。
轉載自:
3種web會話管理的方式
看圖了解JWT如何用于單點登入
參考文獻:
https://blog.csdn.net/qq_38401919/article/details/80535258