一、單點登錄的介紹
單點登錄(Single Sign On),簡稱為 SSO,是目前比較流行的企業業務整合的解決方案之一。SSO的定義是在多個應用系統中,用戶只需要登錄一次就可以訪問所有相互信任的應用系統。
例如:百度旗下有很多的產品,比如百度貼吧、百度知道、百度文庫等,只要登錄百度賬號,在任何一個地方都是已登錄狀態,不需要重新登錄。
當用戶第一次訪問應用系統的時候,因為還沒有登錄,會被引導到認證系統中進行登錄;根據用戶提供的登錄信息,認證系統進行身份校驗,如果通過校驗,應該返回給用戶一個認證的憑據--ticket;用戶再訪問別的應用的時候,就會將這個ticket帶上,作為自己認證的憑據,應用系統接受到請求之后會把ticket送到認證系統進行校驗,檢查ticket的合法性。如果通過校驗,用戶就可以在不用再次登錄的情況下訪問應用系統2和應用系統3了。

-
所有應用系統共享一個身份認證系統。
統一的認證系統是SSO的前提之一。認證系統的主要功能是將用戶的登錄信息和用戶信息庫相比較,對用戶進行登錄認證;認證成功后,認證系統應該生成統一的認證標志(ticket),返還給用戶。另外,認證系統還應該對ticket進行效驗,判斷其有效性。 -
所有應用系統能夠識別和提取ticket信息
要實現SSO的功能,讓用戶只登錄一次,就必須讓應用系統能夠識別已經登錄過的用戶。應用系統應該能對ticket進行識別和提取,通過與認證系統的通訊,能自動判斷當前用戶是否登錄過,從而完成單點登錄的功能。
二、單點登錄技術實現機制
在說單點登錄(SSO)的技術實現之前,我們先說一說普通的登錄認證機制。
如上圖所示,我們在瀏覽器(Browser)中訪問一個應用,這個應用需要登錄,我們填寫完用戶名和密碼后,完成登錄認證。這時,我們在這個用戶的session中標記登錄狀態為yes(已登錄),同時在瀏覽器(Browser)中寫入Cookie,這個Cookie是這個用戶的唯一標識。下次我們再訪問這個應用的時候,請求中會帶上這個Cookie,服務端會根據這個Cookie找到對應的session,通過session來判斷這個用戶是否登錄。如果不做特殊配置,這個Cookie的名字叫做jsessionid,值在服務端(server)是唯一的。
1、同域下的單點登錄
一個企業一般情況下只有一個域名,通過二級域名區分不同的系統。比如我們有個域名叫做:a.com,同時有兩個業務系統分別為:app1.a.com和app2.a.com。我們要做單點登錄(SSO),需要一個登錄系統,叫做:sso.a.com。
我們只要在sso.a.com登錄,app1.a.com和app2.a.com就也登錄了。通過上面的登陸認證機制,我們可以知道,在sso.a.com中登錄了,其實是在sso.a.com的服務端的session中記錄了登錄狀態,同時在瀏覽器端(Browser)的sso.a.com下寫入了Cookie。那么我們怎么才能讓app1.a.com和app2.a.com登錄呢?這里有兩個問題:
- Cookie是不能跨域的,我們Cookie的domain屬性是sso.a.com,在給app1.a.com和app2.a.com發送請求是帶不上的。
- sso、app1和app2是不同的應用,它們的session存在自己的應用內,是不共享的。
那么我們如何解決這兩個問題呢?針對第一個問題,sso登錄以后,可以將Cookie的域設置為頂域,即.a.com,這樣所有子域的系統都可以訪問到頂域的Cookie。我們在設置Cookie時,只能設置頂域和自己的域,不能設置其他的域。比如:我們不能在自己的系統中給baidu.com的域設置Cookie。
Cookie的問題解決了,我們再來看看session的問題。我們在sso系統登錄了,這時再訪問app1,Cookie也帶到了app1的服務端(Server),app1的服務端怎么找到這個Cookie對應的Session呢?這里就要把3個系統的Session共享,如圖所示。共享Session的解決方案有很多,例如:Spring-Session。這樣第2個問題也解決了。
同域下的單點登錄就實現了,但這還不是真正的單點登錄。
2、不同域下的單點登錄
同域下的單點登錄是巧用了Cookie頂域的特性。如果是不同域呢?不同域之間Cookie是不共享的,怎么辦?
這里我們就要說一說CAS流程了,這個流程是單點登錄的標准流程。
上圖是CAS官網上的標准流程,具體流程如下:
- 用戶訪問app系統,app系統是需要登錄的,但用戶現在沒有登錄。
- 跳轉到CAS server,即SSO登錄系統,以后圖中的CAS Server我們統一叫做SSO系統。 SSO系統也沒有登錄,彈出用戶登錄頁。
- 用戶填寫用戶名、密碼,SSO系統進行認證后,將登錄狀態寫入SSO的session,瀏覽器(Browser)中寫入SSO域下的Cookie。
- SSO系統登錄完成后會生成一個ST(Service Ticket),然后跳轉到app系統,同時將ST作為參數傳遞給app系統。
- app系統拿到ST后,從后台向SSO發送請求,驗證ST是否有效。
- 驗證通過后,app系統將登錄狀態寫入session並設置app域下的Cookie。
至此,跨域單點登錄就完成了。以后我們再訪問app系統時,app就是登錄的。接下來,我們再看看訪問app2系統時的流程。
- 用戶訪問app2系統,app2系統沒有登錄,跳轉到SSO。
- 由於SSO已經登錄了,不需要重新登錄認證。
- SSO生成ST,瀏覽器跳轉到app2系統,並將ST作為參數傳遞給app2。
- app2拿到ST,后台訪問SSO,驗證ST是否有效。
- 驗證成功后,app2將登錄狀態寫入session,並在app2域下寫入Cookie。
這樣,app2系統不需要走登錄流程,就已經是登錄了。SSO,app和app2在不同的域,它們之間的session不共享也是沒問題的。
有的同學問我,SSO系統登錄后,跳回原業務系統時,帶了個參數ST,業務系統還要拿ST再次訪問SSO進行驗證,覺得這個步驟有點多余。他想SSO登錄認證通過后,通過回調地址將用戶信息返回給原業務系統,原業務系統直接設置登錄狀態,這樣流程簡單,也完成了登錄,不是很好嗎?
其實這樣問題時很嚴重的,如果我在SSO沒有登錄,而是直接在瀏覽器中敲入回調的地址,並帶上偽造的用戶信息,是不是業務系統也認為登錄了呢?這是很可怕的。
總結
單點登錄(SSO)的所有流程都介紹完了,原理大家都清楚了。總結一下單點登錄要做的事情:
- 單點登錄(SSO系統)是保障各業務系統的用戶資源的安全 。
- 各個業務系統獲得的信息是,這個用戶能不能訪問我的資源。
- 單點登錄,資源都在各個業務系統這邊,不在SSO那一方。 用戶在給SSO服務器提供了用戶名密碼后,作為業務系統並不知道這件事。 SSO隨便給業務系統一個ST,那么業務系統是不能確定這個ST是用戶偽造的,還是真的有效,所以要拿着這個ST去SSO服務器再問一下,這個用戶給我的ST是否有效,是有效的我才能讓這個用戶訪問。
三、單點登錄優缺點
優點
缺點
歡迎關注微信公眾號【Java典籍】,收看更多Java技術干貨!關注即送java全套資料一份
▼微信掃一掃下圖↓↓↓二維碼關注