不論是什麼公司,只要產品數量大於一個,那麼單點登陸勢必是繞不過去的一個問題。做爲前端程序員,咱們對其雖然接觸很少,但適當的瞭解仍是必要的。本文就來談談單點登陸相關的問題。html
前置知識
瞭解 SSO,最好具有如下知識。固然,若是不是特別熟,也不影響閱讀。前端
- cookie及session
- 瀏覽器同源策略及跨域
- 瞭解登陸系統的構成
什麼是 SSO 與 CAS?
SSO
SSO 是英文 Single Sign On 的縮寫,翻譯過來就是單點登陸。顧名思義,它把兩個及以上個產品中的用戶登陸邏輯抽離出來,達到只輸入一次用戶名密碼,就能同時登陸多個產品的效果。git
打個比方,SSO 和咱們去迪士尼玩時購買的通票很像。
程序員
咱們只要買一次通票,就能夠玩全部遊樂場內的設施,而不須要在過山車或者摩天輪那裏從新買一次票。在這裏,買票就至關於登陸認證,遊樂場就至關於使用一套 SSO 的公司,各類遊樂設施就至關於公司的各個產品。github
![](http://static.javashuo.com/static/loading.gif)
使用 SSO 的優勢很明顯:後端
就以我廠爲例。我廠有兩個產品,丁香人才網和丁香園論壇,假如你是我廠用戶,確定沒法忍受登陸丁香園論壇的時候輸入一次用戶名密碼,登陸人才網又要輸入一次用戶名密碼吧?
假如你是我廠後端,天天任務都飽和的不行,確定沒法忍受到人才網開發一套登陸邏輯,到論壇又開發一套登陸邏輯吧?
假如你是我廠運維,發現了一個安全隱患須要緊急修復。你確定沒法忍受給茫茫多的產品後端都發一封郵件,責令修復吧?萬一漏了一個呢?跨域
綜合看來,SSO 不只是有用的,並且是必要的。瀏覽器
CAS
SSO 僅僅是一種架構,一種設計,而 CAS 則是實現 SSO 的一種手段。二者是抽象與具體的關係。固然,除了 CAS 以外,實現 SSO 還有其餘手段,好比簡單的 cookie。緩存
CAS (Central Authentication Service)中心受權服務,自己是一個開源協議,分爲 1.0 版本和 2.0 版本。1.0 稱爲基礎模式,2.0稱爲代理模式,適用於存在非 Web 應用之間的單點登陸。本文只涉及 CAS 1.0,下文中將詳細介紹。安全
SSO 的演進與分類
下面詳述一下各類場景下的 SSO,它們之間是逐步升級,逐步複雜化的關係。
1.同域 SSO
如圖,同域 SSO 是最簡單的一種狀況。
此時,兩個產品都是在一個域名下,單點登陸是很天然的選擇。咱們來捋一捋步驟,搞清楚這裏的步驟是理解後文的基礎,千萬不要跳過。
- 用戶訪問產品 a,向 後臺服務器發送登陸請求。
- 登陸認證成功,服務器把用戶的登陸信息寫入 session。
- 服務器爲該用戶生成一個 cookie,並加入到 response header 中,隨着請求返回而寫入瀏覽器。該 cookie 的域設定爲 dxy.cn。
- 下一次,當用戶訪問同域名的產品 b 時,因爲 a 和 b 在同一域名下,也是 dxy.cn,瀏覽器會自動帶上以前的 cookie。此時後臺服務器就能夠經過該 cookie 來驗證登陸狀態了。
實際上,這種場景就是最簡單最傳統的登陸操做。雖然咱們把產品 a 和 b 人爲分開了,但因爲它們在同域上,就算當作是同一產品的不一樣類目也何嘗不可。咱們沒有設置獨立的 SSO 服務器,由於業務後臺服務器自己就足以承擔 SSO 的職能。
![](http://static.javashuo.com/static/loading.gif)
2.同父域 SSO
同父域 SSO 是同域 SSO 的簡單升級,惟一的不一樣在於,服務器在返回 cookie 的時候,要把cookie 的 domain 設置爲其父域。
好比兩個產品的地址分別爲 a.dxy.cn 和 b.dxy.cn,那麼 cookie 的域設置爲 dxy.cn 便可。在訪問 a 和 b 時,這個 cookie 都能發送到服務器,本質上和同域 SSO 沒有區別。
3.跨域 SSO
能夠看到,在上面兩種狀況下,咱們都沒有專門設置 SSO 服務器。可是當兩個產品不一樣域時,cookie 沒法共享,因此咱們必須設置獨立的 SSO 服務器了。這個時候,咱們就是經過標準的 CAS 方案來實現 SSO 的。下面咱們就來詳細介紹一下:
詳解CAS
CAS 1.0 協議定義了一組術語,一組票據,一組接口。
術語:
- Client:用戶。
- Server:中心服務器,也是 SSO 中負責單點登陸的服務器。
- Service:須要使用單點登陸的各個服務,至關於上文中的產品 a/b。
接口:
- /login:登陸接口,用於登陸到中心服務器。
- /logout:登出接口,用於從中心服務器登出。
- /validate:用於驗證用戶是否登陸中心服務器。
- /serviceValidate:用於讓各個 service 驗證用戶是否登陸中心服務器。
票據
- TGT:Ticket Grangting Ticket
TGT 是 CAS 爲用戶簽發的登陸票據,擁有了 TGT,用戶就能夠證實本身在 CAS 成功登陸過。TGT 封裝了 Cookie 值以及此 Cookie 值對應的用戶信息。當 HTTP 請求到來時,CAS 以此 Cookie 值(TGC)爲 key 查詢緩存中有無 TGT ,若是有的話,則相信用戶已登陸過。
- TGC:Ticket Granting Cookie
CAS Server 生成TGT放入本身的 Session 中,而 TGC 就是這個 Session 的惟一標識(SessionId),以 Cookie 形式放到瀏覽器端,是 CAS Server 用來明確用戶身份的憑證。
ST 是 CAS 爲用戶簽發的訪問某一 service 的票據。用戶訪問 service 時,service 發現用戶沒有 ST,則要求用戶去 CAS 獲取 ST。用戶向 CAS 發出獲取 ST 的請求,CAS 發現用戶有 TGT,則簽發一個 ST,返回給用戶。用戶拿着 ST 去訪問 service,service 拿 ST 去 CAS 驗證,驗證經過後,容許用戶訪問資源。
票據之間的關係以下圖。注意,PGTIOU, PGT, PT 是 CAS 2.0 中的內容,感興趣的同窗能夠自行了解。
![](http://static.javashuo.com/static/loading.gif)
詳細步驟
看到這裏,是否是又有點暈了?不要緊,下面咱們藉助一個簡單的場景,再來仔細捋一捋用 CAS 實現 SSO 的詳細步驟,順便加深理解以前提出的概念。
開始!
- 用戶訪問產品 a,域名是 www.a.cn。
- 因爲用戶沒有攜帶在 a 服務器上登陸的 a cookie,因此 a 服務器返回 http 重定向,重定向的 url 是 SSO 服務器的地址,同時 url 的 query 中經過參數指明登陸成功後,回跳到 a 頁面。重定向的url 形如 sso.dxy.cn/login?service=https%3A%2F%2Fwww.a.cn。
- 因爲用戶沒有攜帶在 SSO 服務器上登陸的 TGC(看上面,票據之一),因此 SSO 服務器判斷用戶未登陸,給用戶顯示統一登陸界面。用戶在 SSO 的頁面上進行登陸操做。
- 登陸成功後,SSO 服務器構建用戶在 SSO 登陸的 TGT(又一個票據),同時返回一個 http 重定向。這裏注意:
- 重定向地址爲以前寫在 query 裏的 a 頁面。
- 重定向地址的 query 中包含 sso 服務器派發的 ST。
- 重定向的 http response 中包含寫 cookie 的 header。這個 cookie 表明用戶在 SSO 中的登陸狀態,它的值就是 TGC。
- 瀏覽器重定向到產品 a。此時重定向的 url 中攜帶着 SSO 服務器生成的 ST。
- 根據 ST,a 服務器向 SSO 服務器發送請求,SSO 服務器驗證票據的有效性。驗證成功後,a 服務器知道用戶已經在 sso 登陸了,因而 a 服務器構建用戶登陸 session,記爲 a session。並將 cookie 寫入瀏覽器。注意,此處的 cookie 和 session 保存的是用戶在 a 服務器的登陸狀態,和 CAS 無關。
- 以後用戶訪問產品 b,域名是 www.b.cn。
- 因爲用戶沒有攜帶在 b 服務器上登陸的 b cookie,因此 b 服務器返回 http 重定向,重定向的 url 是 SSO 服務器的地址,去詢問用戶在 SSO 中的登陸狀態。
- 瀏覽器重定向到 SSO。注意,第 4 步中已經向瀏覽器寫入了攜帶 TGC 的cookie,因此此時 SSO 服務器能夠拿到,根據 TGC 去查找 TGT,若是找到,就判斷用戶已經在 sso 登陸過了。
- SSO 服務器返回一個重定向,重定向攜帶 ST。注意,這裏的 ST 和第4步中的 ST 是不同的,事實上,每次生成的 ST 都是不同的。
- 瀏覽器帶 ST 重定向到 b 服務器,和第 5 步同樣。
- b 服務器根據票據向 SSO 服務器發送請求,票據驗證經過後,b 服務器知道用戶已經在 sso 登陸了,因而生成 b session,向瀏覽器寫入 b cookie。
![](http://static.javashuo.com/static/loading.gif)
如圖所示,至此,整個登陸流程結束。以後當用戶訪問 a 或者 b 後,直接會攜帶 a cookie/b cookie,就不用再向 SSO 確認了。
實際開發時,能夠根據 CAS 增長更多的判斷邏輯,好比,在收到CAS Server簽發的ST後,若是 ST 被 hacker 竊取,而且 client 自己沒來得及去驗證 ST,被 hacker 搶先一步驗證 ST,怎麼解決。此時就能夠在申請 ST 時添加額外驗證因子(如ip、sessionId等)。
參考閱讀: