最近在項(xiàng)目中遇到了很多關(guān)于認(rèn)證 & 授權(quán)的事情,狀態(tài)不好的時(shí)候,時(shí)不時(shí)把自己繞進(jìn)去了,需要記下來避免再犯錯(cuò),由簡單到難
什么是認(rèn)證&授權(quán)
Authentication vs. Authorization
It is easy to confuse authentication with another element of the security plan: authorization. While authentication verifies the user’s identity, authorization verifies that the user in question has the correct permissions and rights to access the requested resource. As you can see, the two work together. Authentication occurs first, then authorization.
概念
1.HTTP 身份驗(yàn)證
HTTP 提供一個(gè)用于權(quán)限控制和認(rèn)證的通用框架。最常用的HTTP認(rèn)證方案是HTTP Basic authentication。本頁介紹了通用的HTTP認(rèn)證框架以及展示如何通過HTTP Basic authentication來限制權(quán)限訪問您的服務(wù)器。
通用的 HTTP 認(rèn)證框架
定義了一個(gè) HTTP 身份驗(yàn)證框架,服務(wù)器可以用來針對(duì)客戶端的請求發(fā)送 challenge,客戶端則可以用來提供身份驗(yàn)證憑證。質(zhì)詢與應(yīng)答的工作流程如下:服務(wù)器端向客戶端返回 401
(Unauthorized,未被授權(quán)的) 狀態(tài)碼,并在 WWW-Authenticate
首部提供如何進(jìn)行驗(yàn)證的信息,其中至少包含有一種質(zhì)詢方式。之后有意向證明自己身份的客戶端可以在新的請求中添加 Authorization
首部字段進(jìn)行驗(yàn)證,字段值為身份驗(yàn)證憑證信息。通常客戶端會(huì)彈出一個(gè)密碼框讓用戶填寫,然后發(fā)送包含有恰當(dāng)?shù)?Authorization
首部的請求。
步驟如下:
1.當(dāng)打開需要認(rèn)證的頁面時(shí),會(huì)彈出一個(gè)對(duì)話框,要求輸入用戶名和密碼
2.使用Fiddler監(jiān)聽請求,可以看到在未進(jìn)行認(rèn)證或認(rèn)證失敗的情況下,服務(wù)端會(huì)返回401 Unauthorized
給客戶端,并附帶Challenge(質(zhì)詢),即在Response Header中添加WWW-Authenticate
標(biāo)頭,瀏覽器識(shí)別到Basic后彈出對(duì)話框
Realm
表示W(wǎng)eb服務(wù)器中受保護(hù)文檔的安全域(比如公司財(cái)務(wù)信息域和公司員工信息域),用來指示需要哪個(gè)域的用戶名和密碼,用" "
包括起來(截圖中沒有,但最好加上)。
3.輸入正確的用戶名和密碼,認(rèn)證成功后,瀏覽器會(huì)將憑據(jù)信息緩存起來,那么以后再進(jìn)入時(shí),無需重復(fù)手動(dòng)輸入用戶名和密碼。
查看HTTP請求,可以看到Request Header中添加了Authorization
標(biāo)頭,格式為:Authorization: <type> <credentials>
- 類型為“Basic”
-
憑證為“MTIzOjEyMw==”,是通過將“用戶名:密碼”格式的字符串經(jīng)過的Base64編碼得到的。而Base64不屬于加密范疇,可以被逆向解碼,等同于明文,因此Basic傳輸認(rèn)證信息是不安全的
image.png
三、缺陷
1.用戶名和密碼明文(Base64)傳輸,需要配合HTTPS來保證信息傳輸?shù)陌踩?br>
2.即使密碼被強(qiáng)加密,第三方仍可通過加密后的用戶名和密碼進(jìn)行重放攻擊。
3.沒有提供任何針對(duì)代理和中間節(jié)點(diǎn)的防護(hù)措施。
4.假冒服務(wù)器很容易騙過認(rèn)證,誘導(dǎo)用戶輸入用戶名和密碼。
Token
Token的引入
Token是在客戶端頻繁向服務(wù)端請求數(shù)據(jù),服務(wù)端頻繁的去數(shù)據(jù)庫查詢用戶名和密碼并進(jìn)行對(duì)比,判斷用戶名和密碼正確與否,并作出相應(yīng)提示,在這樣的背景下,Token便應(yīng)運(yùn)而生。
Token的定義
Token是服務(wù)端生成的一串字符串,以作客戶端進(jìn)行請求的一個(gè)令牌,當(dāng)?shù)谝淮蔚卿浐螅?wù)器生成一個(gè)Token便將此Token返回給客戶端,以后客戶端只需帶上這個(gè)Token前來請求數(shù)據(jù)即可,無需再次帶上用戶名和密碼。
使用Token的目的
Token的目的是為了減輕服務(wù)器的壓力,減少頻繁的查詢數(shù)據(jù)庫,使服務(wù)器更加健壯。
為什么要用 Token:
Token 完全由應(yīng)用管理,所以它可以避開同源策略
Token 可以避免 CSRF 攻擊(http://dwz.cn/7joLzx)
Token 可以是無狀態(tài)的,可以在多個(gè)服務(wù)間共享
基于 Token 的身份驗(yàn)證方法
1.客戶端使用用戶名跟密碼請求登錄
2.服務(wù)端收到請求,去驗(yàn)證用戶名與密碼
3.驗(yàn)證成功后,服務(wù)端會(huì)簽發(fā)一個(gè) Token,再把這個(gè) Token 發(fā)送給客戶端
4.客戶端收到 Token 以后可以把它存儲(chǔ)起來,比如放在 Cookie 里或者 Local Storage 里
5.客戶端每次向服務(wù)端請求資源的時(shí)候需要帶著服務(wù)端簽發(fā)的 Token
6.服務(wù)端收到請求,然后去驗(yàn)證客戶端請求里面帶著的 Token,如果驗(yàn)證成功,就向客戶端返回請求的數(shù)據(jù)
Token 時(shí)序圖
1.登陸
2.Token 過期,刷新 Token
使用 Refresh Token,它可以避免頻繁的讀寫操作。這種方案中,服務(wù)端不需要刷新 Token 的過期時(shí)間,一旦 Token 過期,就反饋給前端,前端使用 Refresh Token 申請一個(gè)全新 Token 繼續(xù)使用。這種方案中,服務(wù)端只需要在客戶端請求更新 Token 的時(shí)候?qū)?Refresh Token 的有效性進(jìn)行一次檢查,大大減少了更新有效期的操作,也就避免了頻繁讀寫。當(dāng)然 Refresh Token 也是有有效期的,但是這個(gè)有效期就可以長一點(diǎn)了,比如,以天為單位的時(shí)間。
分離認(rèn)證服務(wù)
當(dāng) Token 無狀態(tài)之后,單點(diǎn)登錄就變得容易了。前端拿到一個(gè)有效的 Token,它就可以在任何同一體系的服務(wù)上認(rèn)證通過——只要它們使用同樣的密鑰和算法來認(rèn)證 Token 的有效性。就樣這樣:
當(dāng)然,如果 Token 過期了,前端仍然需要去認(rèn)證服務(wù)更新 Token:
JWT
JWT 是Json Web Tokens的簡稱。用百度上面的解釋講,是目前流行的跨域認(rèn)證解決方案,一種基于JSON的、用于在網(wǎng)絡(luò)上聲明某種主張的令牌(token)。
JWT原理
jwt驗(yàn)證方式是將用戶信息通過加密生成token,每次請求服務(wù)端只需要使用保存的密鑰驗(yàn)證token的正確性,不用再保存任何session數(shù)據(jù)了,進(jìn)而服務(wù)端變得無狀態(tài),容易實(shí)現(xiàn)拓展。
JWT原理:服務(wù)端認(rèn)證完之后,生成一個(gè)JSON對(duì)象返回個(gè)用戶,后續(xù)客戶端所有請求都會(huì)帶上這個(gè)JSON對(duì)象,服務(wù)端依靠這個(gè)JSON來驗(yàn)證認(rèn)定用戶身份
JWT組成
{
"username": "vist",
"role": "admin",
"expire": "2020-11-06 15:14:20"
}
6gdfg7af816b907f2cc9acbe9c3b4625
載荷
載荷是數(shù)據(jù)的主體部分。一般使用base64編碼。
可以使用JWT官方推薦字段:
iss: 簽發(fā)者
sub: 主題
aud: 接收者
exp(expires): 過期時(shí)間
iat(issued at): 簽發(fā)時(shí)間
nbf(not before): 早于某個(gè)時(shí)間不處理
jti(JWT ID): 唯一標(biāo)識(shí)
簽名
簽名部分是對(duì)前兩部分(頭部,載荷)的簽名,防止數(shù)據(jù)篡改。
按下列步驟生成:
1、先指定密鑰(secret)
2、把頭部(header)和載荷(payload)信息分別base64轉(zhuǎn)換
3、使用頭部(header)指定的算法加密
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), "密鑰/鹽");
JWT的特點(diǎn)
JWT更加簡潔,更適合在HTML和HTTP環(huán)境中傳遞。,但更建議JWT建議使用HTTPS協(xié)議來傳輸代碼。
JWT適合一次性驗(yàn)證,如:激活郵件
JWT適合無狀態(tài)認(rèn)證
JWT適合服務(wù)端CDN分發(fā)內(nèi)容
相對(duì)于數(shù)據(jù)庫Session查詢更加省時(shí)
跨域認(rèn)證需要做Session共享,而使用了JWT則不需要。因?yàn)橹灰渌?wù)器只要是使用同一套算法,就可以做信息的校驗(yàn)。
JWT默認(rèn)不加密,使用期間不可取消令牌或更改令牌的權(quán)限
token和jwt存在什么區(qū)別
相同: 都是訪問資源的令牌, 都可以記錄用戶信息,都是只有驗(yàn)證成功后
區(qū)別:服務(wù)端驗(yàn)證客戶端發(fā)來的token信息要進(jìn)行數(shù)據(jù)的查詢操作;JWT驗(yàn)證客戶端發(fā)來的token信息就不用, 在服務(wù)端使用密鑰校驗(yàn)就可以,不用數(shù)據(jù)庫的查詢。
什么是IDP
身份提供者 (IDP) 是一種數(shù)字服務(wù),它創(chuàng)建和管理用戶的數(shù)字身份和與之相關(guān)的身份屬性。 IDP 使用這些身份向第三方服務(wù)提供商(如網(wǎng)站、Web 應(yīng)用程序等)驗(yàn)證用戶。
IDP 允許用戶將自己的身份帶入他們的工作區(qū),并使他們能夠使用現(xiàn)有的一組憑據(jù)注冊/登錄到 Web 服務(wù)或應(yīng)用程序,而不是為服務(wù)或應(yīng)用程序創(chuàng)建新的憑據(jù)。
我們大多數(shù)人都熟悉的身份提供者的一個(gè)流行示例是 Google。 “使用 Google 注冊”或“使用 Google 登錄”選項(xiàng)是 Google 作為我們正在登錄或登錄的服務(wù)的身份提供者的一個(gè)示例。 這樣用戶就可以使用他們的 Google ID 訪問服務(wù)及其資源。
什么是Keycloack
Keycloak是為現(xiàn)代應(yīng)用系統(tǒng)和服務(wù)提供開源的認(rèn)證和授權(quán)訪問控制管理。Keycloak 實(shí)現(xiàn)了OpenID、OAuth2.0、SAML單點(diǎn)登錄協(xié)議,同時(shí)提供 LDAP 和 Active Directory 以及 OpenID Connect、SAML2.0 IdPs、Github、Google 等第三方登錄適配功能,能夠做到非常簡單的開箱即用。提供的功能如下:
1.Keycloak通過配置,可實(shí)現(xiàn)對(duì)不同身份認(rèn)證服務(wù)的集成,通過這些身份認(rèn)證服務(wù)登錄應(yīng)用
2.在企業(yè)系統(tǒng)中有使用LDAP/AD管理用戶,同樣,Keycloak 提供了對(duì)LDAP/AD的集成方案,可以方便的同步用戶。
3.Keycloak提供了多種語言和不同平臺(tái)的支持,支持標(biāo)準(zhǔn)協(xié)議,OpenID Connect, OAuth 2.0, and SAML等
OpenID Connect
Java,JBoss EAP,WildFly,F(xiàn)use,Tomcat,Jetty 9,Servlet Filter,Spring Boot,Spring Security,JavaScript,Node.js,C#,Python,Android,iOS,Apache HTTP Server
SAML
Java,JBoss EAP,WildFly,Tomcat,Jetty,Apache HTTP Server
什么是SAML
SAML即安全斷言標(biāo)記語言,英文全稱是Security Assertion Markup Language。它是一個(gè)基于XML的標(biāo)準(zhǔn),用于在不同的安全域(security domain)之間交換認(rèn)證和授權(quán)數(shù)據(jù)。在SAML標(biāo)準(zhǔn)定義了身份提供者(identity provider)和服務(wù)提供者(service provider),這兩者構(gòu)成了前面所說的不同的安全域。 SAML是OASIS組織安全服務(wù)技術(shù)委員會(huì)(Security Services Technical Committee)的產(chǎn)品。
SAML(Security Assertion Markup Language)是一個(gè)XML框架,也就是一組協(xié)議,可以用來傳輸安全聲明。比如,兩臺(tái)遠(yuǎn)程機(jī)器之間要通訊,為了保證安全,我們可以采用加密等措施,也可以采用SAML來傳輸,傳輸?shù)臄?shù)據(jù)以XML形式,符合SAML規(guī)范,這樣我們就可以不要求兩臺(tái)機(jī)器采用什么樣的系統(tǒng),只要求能理解SAML規(guī)范即可,顯然比傳統(tǒng)的方式更好。SAML 規(guī)范是一組Schema 定義。
SAML流程的參與者包括Service Provider(SP)和Identity Provider(IDP)兩個(gè)重要角色,且整個(gè)流程包括如下兩個(gè)使用場景:
? SP Initiated: 服務(wù)提供者主動(dòng)發(fā)起
? IDP Initiated: 身份認(rèn)證服務(wù)器主動(dòng)發(fā)起
下面是大致的認(rèn)證流程:
- End User從瀏覽器中請求訪問某SP:https://www.example.com ;
- https://www.example.com發(fā)現(xiàn)用戶未登陸,則發(fā)起SAML的AuthnRequest請求至IDP, 用戶瀏覽器跳轉(zhuǎn)至IDP頁面;
- IDP發(fā)現(xiàn)用戶處于未登陸狀態(tài),重定向用戶至IDP的登陸界面,請求用戶進(jìn)行身份驗(yàn)證
- 用戶在登陸頁面中進(jìn)行身份認(rèn)證, 通常情況下需要校驗(yàn)用戶名和密碼;
- IDP校驗(yàn)用戶身份,若成功,則把包含著用戶身份信息的校驗(yàn)結(jié)果,以SAML Reponse的形式,簽名/加密發(fā)送給SP;
- SP拿到用戶身份信息以后,進(jìn)行簽名驗(yàn)證/解密,拿到明文的用戶身份信息,此時(shí)SP處于登陸狀態(tài),可以對(duì)用戶提供服務(wù)。
可以看到,在整個(gè)流程中,IDP是負(fù)責(zé)頒發(fā)用戶身份,SP負(fù)責(zé)信任IDP頒發(fā)的用戶身份, SP和IDP之間的信任關(guān)系是需要提前建立的,即SP和IDP需要提前把雙方的信息預(yù)先配置到對(duì)方,通過證書信任的方式來建立互信。
什么是OIDC
OIDC 的全稱是 OpenID Connect,是一套基于 OAuth 2.0 的認(rèn)證 + 授權(quán)協(xié)議,用于用戶身份認(rèn)證,將用戶數(shù)據(jù)安全地暴露給第三方。
以上是 OAuth 2.0 的官方定義。我們舉一個(gè)實(shí)際的例子,你在登錄京東的時(shí)候,會(huì)發(fā)現(xiàn)在京東的登錄框中有使用 QQ 登錄、使用 QQ 登錄的按鈕,這些地方就是 OAuth 2.0 協(xié)議的用武之地。京東希望從 QQ 獲取你的 QQ 用戶數(shù)據(jù),從而完成在京東的注冊,這就需要數(shù)據(jù)的主人——你的授權(quán)。完成授權(quán)之后, QQ 會(huì)給京東一個(gè) access_token,京東攜帶這個(gè)憑證,就能以你的名義,以及你授予此網(wǎng)站的權(quán)限(例如你授權(quán)京東能夠訪問你的個(gè)人信息而不是轉(zhuǎn)賬能力),訪問你在 QQ 服務(wù)器上的數(shù)據(jù),從而獲取你的信息,在此過程中,你無須告訴京東你的 QQ** 賬號(hào)和密碼**,你輸入賬密信息的時(shí)候,是在騰訊的服務(wù)器完成的認(rèn)證。
OIDC 與 OAuth 2.0 相比,多了認(rèn)證的能力。不但能夠返回用戶的 access_token,讓第三方通過 access_token 調(diào)用用戶授權(quán)過的接口(用戶授權(quán)),還可以返回用戶的 id_token,第三方可以將 id_token 用作用戶身份標(biāo)識(shí)(用戶認(rèn)證)。
回到剛才的例子,京東獲取到 QQ 頒發(fā)的 access_token (是一個(gè)隨機(jī)字符串)之后確實(shí)能夠獲取到你的信息,但是如果不借助其他手段,是不具備用戶身份認(rèn)證功能的。而在 OIDC 協(xié)議中,獲取 access_token 的同時(shí),會(huì)返回一個(gè) JWT 格式的 id_token,可直接用作身份標(biāo)識(shí),供第三方確認(rèn)用戶身份。
OIDC 協(xié)議中的四個(gè)主體
在介紹 OIDC 授權(quán)模式之前,先要明確四個(gè)主體:第三方應(yīng)用、資源服務(wù)器、資源所有者、認(rèn)證授權(quán)服務(wù)器。我們繼續(xù)沿用前文京東與 QQ 登錄的例子。
第三方應(yīng)用
京東的角色是第三方應(yīng)用。
資源服務(wù)器
QQ 的個(gè)人信息存放于資源服務(wù)器。
資源所有者
用戶是 QQ 賬號(hào)的所有者。
認(rèn)證授權(quán)服務(wù)器
QQ 的授權(quán)服務(wù)器負(fù)責(zé)用戶的身份認(rèn)證和授權(quán),管理第三方應(yīng)用、受保護(hù)資源、資源所有者之間的關(guān)系
OIDC 的三種授權(quán)模式
應(yīng)用最為廣泛的是授權(quán)碼模式,此模式的交互過程如下圖
- 第三方應(yīng)用訪問認(rèn)證服務(wù)器的授權(quán)鏈接。(用戶在京東網(wǎng)站登錄框點(diǎn)擊使用 QQ 登錄)
- 用戶與認(rèn)證服務(wù)器完成身份認(rèn)證。(瀏覽器跳轉(zhuǎn)到 QQ 授權(quán)頁面,用戶輸入 QQ 號(hào)和密碼)
- 認(rèn)證服務(wù)器向第三方應(yīng)用返回授權(quán)碼 code。(QQ 服務(wù)器將用戶的瀏覽器重定向,將授權(quán)碼發(fā)送到京東服務(wù)器)
- 第三方應(yīng)用攜帶授權(quán)碼訪問認(rèn)證服務(wù)器的 token 接口。(京東服務(wù)器攜帶授權(quán)碼與 QQ 服務(wù)器交互)
- 認(rèn)證服務(wù)器返回 access_token 和 id_token 給第三方應(yīng)用。(QQ 服務(wù)器返回 access_token 和 id_token 給京東服務(wù)器
此后,第三方應(yīng)用可以利用 access_token 到資源服務(wù)器獲取用戶的信息,完成在第三方應(yīng)用的注冊和登錄業(yè)務(wù),并可以將 id_token 作為用戶的身份憑證,存放在前端。第三方應(yīng)用的前端需要訪問受保護(hù)的資源(例如用戶賬單信息、購物車)時(shí)需要攜帶 id_token,后端驗(yàn)證 id_token 合法性,核實(shí)用戶身份之后,返回相關(guān)資源數(shù)據(jù)。
Implicit Flow
在隱式模式中,認(rèn)證服務(wù)器的授權(quán)接口不會(huì)返回授權(quán)碼 code,而是在與用戶完成認(rèn)證后返回 id_token 和 access_token,交互模式如下圖所示:
- 第三方應(yīng)用訪問認(rèn)證服務(wù)器的授權(quán)鏈接。(用戶在京東網(wǎng)站登錄框點(diǎn)擊使用 QQ 登錄)
- 用戶與認(rèn)證服務(wù)器完成身份認(rèn)證。(瀏覽器跳轉(zhuǎn)到 QQ 授權(quán)頁面,用戶輸入 QQ 號(hào)和密碼)
- 認(rèn)證服務(wù)器向第三方應(yīng)用返回 id_token 和 access_token。(QQ 服務(wù)器將用戶的瀏覽器重定向,將 id_token access_token 發(fā)送到京東前端頁面)
隱式模式比授權(quán)碼模式簡單,經(jīng)常用于將 id_token、access_token 直接返回到前端,方便前端直接存儲(chǔ) id_token 用于證明用戶身份。也需要前端自行將 access_token 發(fā)回后端,后端用于獲取用戶的詳細(xì)信息,這增加了暴露 access_token 的風(fēng)險(xiǎn)。隱式模式不支持返回 refresh_token,即不能從后端刷新 access_token,登錄一旦過期需要用戶重新登錄。
Hybrid Flow
混合模式是以上兩種模式的組合,特點(diǎn)是能夠在授權(quán)接口一次性獲取到 code、id_token、access_token,一般 code 會(huì)與 id_token、access_token 混合出現(xiàn),混合模式的交互如下圖所示:
- 第三方應(yīng)用訪問認(rèn)證服務(wù)器的授權(quán)鏈接。(用戶在京東網(wǎng)站登錄框點(diǎn)擊使用 QQ 登錄)
- 用戶與認(rèn)證服務(wù)器完成身份認(rèn)證。(瀏覽器跳轉(zhuǎn)到 QQ 授權(quán)頁面,用戶輸入 QQ 號(hào)和密碼)
- 認(rèn)證服務(wù)器向第三方應(yīng)用返回 code、id_token 和 access_token。(QQ 服務(wù)器將用戶的瀏覽器重定向,將 id_token access_token 發(fā)送到京東前端頁面)
- 第三方應(yīng)用攜帶授權(quán)碼訪問認(rèn)證服務(wù)器的 token 接口。(京東服務(wù)器攜帶授權(quán)碼與 QQ 服務(wù)器交互)
認(rèn)證服務(wù)器返回 access_token 和 id_token 給第三方應(yīng)用。(QQ 服務(wù)器返回 access_token 和 id_token 給京東服務(wù)器)
SSO 概念
單點(diǎn)登錄(Single Sign On),簡稱為SSO,是目前比較流行的企業(yè)業(yè)務(wù)整合的解決方案之一。SSO是指在多應(yīng)用系統(tǒng)中,用戶只需要在某一個(gè)應(yīng)用上登錄一次,就可以同時(shí)在所有相關(guān)又彼此獨(dú)立的系統(tǒng)中共享登錄態(tài)。即只登錄一次,就能訪問所有相互信任的應(yīng)用系統(tǒng),在其他所有系統(tǒng)中也都得到了授權(quán)而無需再次登錄。另外用戶也只需要退出一次,即可退出所有其他可信的服務(wù)。所以SSO包括單點(diǎn)登錄與單點(diǎn)注銷兩部分。
單點(diǎn)登錄(Single Sign On),簡稱為SSO,是目前比較流行的企業(yè)業(yè)務(wù)整合的解決方案之一。SSO是指在多應(yīng)用系統(tǒng)中,用戶只需要在某一個(gè)應(yīng)用上登錄一次,就可以同時(shí)在所有相關(guān)又彼此獨(dú)立的系統(tǒng)中共享登錄態(tài)。即只登錄一次,就能訪問所有相互信任的應(yīng)用系統(tǒng),在其他所有系統(tǒng)中也都得到了授權(quán)而無需再次登錄。另外用戶也只需要退出一次,即可退出所有其他可信的服務(wù)。所以SSO包括單點(diǎn)登錄與單點(diǎn)注銷兩部分。
根據(jù)上圖,我們可以梳理出單點(diǎn)登錄的請求執(zhí)行流程(重點(diǎn)):
比如用戶訪問系統(tǒng)1的受保護(hù)資源,結(jié)果系統(tǒng)1發(fā)現(xiàn)用戶未登錄,會(huì)先跳轉(zhuǎn)到SSO認(rèn)證中心,并將自己的地址作為參數(shù),比如http://login.xxx.com/jump?target=http://系統(tǒng)1.com/xxx ;
SSO認(rèn)證中心發(fā)現(xiàn)用戶未登錄,則將用戶引導(dǎo)到登錄頁面,并將系統(tǒng)1的地址作為參數(shù)帶過去;
用戶輸入用戶名和密碼,向SSO認(rèn)證中心提交登錄申請,并將系統(tǒng)1的地址作為參數(shù)帶過去;
SSO認(rèn)證中心校驗(yàn)用戶信息,校驗(yàn)成功后,會(huì)創(chuàng)建一個(gè)用戶與SSO認(rèn)證中心之間的會(huì)話,稱之為全局會(huì)話,同時(shí)創(chuàng)建一個(gè)授權(quán)令牌;
SSO認(rèn)證中心帶著令牌跳轉(zhuǎn)回最初的請求地址(系統(tǒng)1);
系統(tǒng)1拿到授權(quán)令牌后,接著去SSO認(rèn)證中心校驗(yàn)令牌是否有效,并將系統(tǒng)1的地址作為參數(shù)帶過去;
SSO認(rèn)證中心先校驗(yàn)令牌是否有效,正常則返回有效信息,并把系統(tǒng)1的信息注冊進(jìn)SSO授權(quán)中心;
系統(tǒng)1使用該授權(quán)令牌創(chuàng)建出與用戶的會(huì)話,稱為局部會(huì)話,然后給用戶返回受保護(hù)的資源;
如果用戶繼續(xù)訪問系統(tǒng)2的受保護(hù)資源,也會(huì)與SSO授權(quán)中心進(jìn)行交互授權(quán);
比如系統(tǒng)2發(fā)現(xiàn)用戶未登錄,則跳轉(zhuǎn)到SSO認(rèn)證中心,并將自己的地址作為參數(shù)攜帶過去;
如果SSO認(rèn)證中心發(fā)現(xiàn)用戶已登錄,則跳轉(zhuǎn)回系統(tǒng)2的地址,并帶過去授權(quán)令牌;
系統(tǒng)2拿到授權(quán)令牌,接著會(huì)去SSO認(rèn)證中心校驗(yàn)授權(quán)令牌是否有效;
SSO認(rèn)證中心也會(huì)校驗(yàn)授權(quán)令牌,并返回有效信息,把系統(tǒng)2的信息也注冊進(jìn)行SSO授權(quán)中心;
系統(tǒng)2使用該授權(quán)令牌創(chuàng)建一個(gè)與用戶的局部會(huì)話,并返回受保護(hù)的資源。
通過以上的SSO單點(diǎn)登錄執(zhí)行流程,我們可以得知,用戶登錄成功之后,會(huì)與SSO認(rèn)證中心及各個(gè)子系統(tǒng)之間建立會(huì)話。用戶與SSO認(rèn)證中心建立的會(huì)話稱為全局會(huì)話,用戶與各個(gè)子系統(tǒng)建立的會(huì)話稱為局部會(huì)話,局部會(huì)話建立之后,用戶訪問子系統(tǒng)受保護(hù)資源將不再通過SSO認(rèn)證中心。全局會(huì)話與局部會(huì)話有如下約束關(guān)系:
局部會(huì)話存在,全局會(huì)話一定存在;
全局會(huì)話存在,局部會(huì)話不一定存在;
全局會(huì)話銷毀,局部會(huì)話必須銷毀。
單點(diǎn)登錄涉及到SSO認(rèn)證中心與眾多子系統(tǒng),各子系統(tǒng)與SSO認(rèn)證中心之間需要通信以交換令牌、校驗(yàn)令牌及發(fā)起注銷請求,因而各子系統(tǒng)必須集成SSO客戶端,SSO認(rèn)證中心則是SSO服務(wù)端,整個(gè)單點(diǎn)登錄過程實(shí)質(zhì)是SSO客戶端與服務(wù)端通信的過程。
單獨(dú)注銷執(zhí)行流程(重點(diǎn))
在多應(yīng)用系統(tǒng)中,我們既然實(shí)現(xiàn)了單點(diǎn)登錄,自然也要單點(diǎn)注銷,即在一個(gè)子系統(tǒng)中注銷后,所有子系統(tǒng)的會(huì)話都將被銷毀。我們用下圖來說明
SSO認(rèn)證中心會(huì)一直監(jiān)聽全局會(huì)話的狀態(tài),一旦發(fā)現(xiàn)全局會(huì)話被銷毀,監(jiān)聽器將通知所有注冊系統(tǒng)執(zhí)行注銷操作。下面對(duì)上圖進(jìn)行簡要說明:
比如用戶向系統(tǒng)1發(fā)起注銷請求;
系統(tǒng)1根據(jù)用戶與系統(tǒng)1建立的局部會(huì)話id拿到授權(quán)令牌,接著系統(tǒng)1向SSO認(rèn)證中心發(fā)起注銷請求;
SSO認(rèn)證中心會(huì)先校驗(yàn)授權(quán)令牌是否有效,然后銷毀全局會(huì)話,同時(shí)取出所有用此授權(quán)令牌注冊的系統(tǒng)地址;
SSO認(rèn)證中心向所有注冊系統(tǒng)發(fā)起注銷會(huì)話的請求;
各注冊系統(tǒng)接收到SSO認(rèn)證中心的注銷請求,銷毀局部會(huì)話;
最后SSO認(rèn)證中心會(huì)引導(dǎo)用戶到登錄頁面。
CAS 概念
CAS(Central Authentication Service),即中心認(rèn)證服務(wù)系統(tǒng)。在CAS系統(tǒng)中,分為CAS Server與CAS Client兩部分,CAS Server是單點(diǎn)登錄系統(tǒng)中負(fù)責(zé)驗(yàn)證的服務(wù)端,CAS Client是CAS Server登錄態(tài)的客戶端。
Ticket Grantfng Ticke(TGT):這是用戶登錄后生成的票根,包含用戶的認(rèn)證身份、有效期等信息,存儲(chǔ)于CAS Server中,類似于我們常見的服務(wù)器會(huì)話;
Ticket Granted Cookie(TGC):這是存儲(chǔ)在Cookie中的一段數(shù)據(jù),類似于會(huì)話ID,用戶與CAS Server進(jìn)行交互時(shí),幫助用戶找到對(duì)應(yīng)的TGT;
Service Ticket(ST):這是CAS Server使用TGT簽發(fā)的一張一次性票據(jù),CAS Client 使用ST與CAS Server進(jìn)行交互,以獲取用戶的驗(yàn)證狀態(tài)。
CAS單點(diǎn)登錄的完整步驟如下:
用戶先通過瀏覽器訪問CAS Client程序的某個(gè)頁面,例如http://cas.client.com/me;
當(dāng)CAS Client判斷用戶需要進(jìn)行身份認(rèn)證時(shí),會(huì)攜帶service作為請求參數(shù),并返回302狀態(tài)碼,指示瀏覽器重定向到CAS Server端,例如 http://cas.server.com/?service=http://cas.client.com/me.service,service是用戶的原訪問頁面;
然后瀏覽器利用 service 重定向到CAS Server;
CAS Server 獲取并校驗(yàn)用戶cookie中攜帶的TGC,如果成功,則身份認(rèn)證完成;否則將用戶重定向到CAS Server 提供的登錄頁,例如 http://cas.server.com/login?service=http://cas.client.com/me,由用戶輸入用戶名和密碼,完成身份認(rèn)證;
如果用戶已經(jīng)登錄過系統(tǒng),那么CAS Server可以直接獲取用戶的TGC,并根據(jù)TGC找到TGT。如果是首次登錄,則CAS Server 會(huì)首先生成TGT。每次驗(yàn)證時(shí),CAS Server 會(huì)根據(jù) TGT簽發(fā)一個(gè)ST,并把ST拼接在service參數(shù)中,同時(shí)將相應(yīng)的TGC設(shè)置到用戶的cookie中(域?yàn)镃AS Server),并返回302 狀態(tài)碼,指示瀏覽器重定向到 service,例如 http://cas.client.com/me?ticket=XXX;
瀏覽器存儲(chǔ)TGC,并攜帶ST重定向到service;
CAS Client取得ST(即請求參數(shù)中的ticket)后,會(huì)向CAS Server請求驗(yàn)證該ST的有效性;
若CAS Server驗(yàn)證該ST是有效的,就告知CAS Client該用戶有效,并返回該用戶的信息。
CAS Client在獲取用戶信息時(shí),可以使用session的形式管理用戶會(huì)話。后續(xù)的交互請求不再需要重定向到CAS Server,CAS Client直接返回用戶請求的資源即可,整個(gè)流程如下圖所示:
CAS 登陸簡單版
CAS單點(diǎn)登錄| 兩次前端跳轉(zhuǎn)、一次后端驗(yàn)證
CAS首次登錄會(huì)經(jīng)過兩次前端跳轉(zhuǎn)、一次后端驗(yàn)證。在應(yīng)用系統(tǒng)端需要集成CasClient的jar包,把其中的filter配置到站點(diǎn)web.xml中,用于攔截請求、判斷登錄、發(fā)起跳轉(zhuǎn)或發(fā)起驗(yàn)證等。在SSO服務(wù)器上部署CasServer的war包,需要配置用戶數(shù)據(jù)源,根據(jù)需求修改登錄頁面。
第一次跳轉(zhuǎn):客戶端訪問應(yīng)用系統(tǒng),應(yīng)用系統(tǒng)判斷Session發(fā)現(xiàn)未登錄,返回302跳轉(zhuǎn)到sso登錄頁面,并傳遞service參數(shù)給sso,該service參數(shù)有兩個(gè)作用:
service一般傳遞應(yīng)用系統(tǒng)url地址,用于sso認(rèn)證通過后回跳到應(yīng)用系統(tǒng);
service參數(shù)同時(shí)會(huì)被cas服務(wù)端的作為cas客戶端的唯一標(biāo)記記錄下來,用于后期匹配相應(yīng)的認(rèn)證憑據(jù);
第二次跳轉(zhuǎn):瀏覽器顯示登錄頁面,用戶輸入賬號(hào)密碼登錄成功后,sso會(huì)返回302跳轉(zhuǎn)回到原來請求的應(yīng)用系統(tǒng)頁面,并攜帶ticket參數(shù),作為認(rèn)證票據(jù),同時(shí)通過Set-Cookie向?yàn)g覽器記錄TGT,(TGT的作用將在下一個(gè)應(yīng)用系統(tǒng)需要登錄的時(shí)候體現(xiàn)出作用,是避免重復(fù)登錄的關(guān)鍵)
一次后臺(tái)驗(yàn)證:應(yīng)用系統(tǒng)接收到帶有ticket的請求后,從后臺(tái)直接向sso服務(wù)器發(fā)起一個(gè)http請求,將service和ticket作為參數(shù),用于驗(yàn)證ticket的有效性;如果ticket有效,sso服務(wù)器將返回該ticket對(duì)應(yīng)的登錄用戶名。