SSO(Single Sign On)單點登錄。SSO是在多個應用系統(tǒng)中,用戶只需要登錄一次就可以訪問所有相互信任的應用系統(tǒng)。它包括可以將這次主要的登錄映射到其他應用中用于同一個用戶的登錄的機制。它是目前比較流行的企業(yè)業(yè)務整合的解決方案之一。
當用戶第一次訪問應用系統(tǒng)1的時候,因為還沒有登錄,會被引導到認證系統(tǒng)中進行登錄;根據(jù)用戶提供的登錄信息,認證系統(tǒng)進行身份校驗,如果通過校驗,應該返回給用戶一個認證的憑據(jù)--ticket;用戶再訪問別的應用的時候就會將這個ticket帶上,作為自己認證的憑據(jù),應用系統(tǒng)接受到請求之后會把ticket送到認證系統(tǒng)進行校驗,檢查ticket的合法性。如果通過校驗,用戶就可以在不用再次登錄的情況下訪問應用系統(tǒng)2和應用系統(tǒng)3了。
WEB-SSO
用戶在訪問頁面1的時候進行了登錄,但是客戶端的每個請求都是單獨的連接,當客戶再次訪問頁面2的時候,如何才能告訴Web服務器,客戶剛才已經(jīng)登錄過了呢?瀏覽器和服務器之間有約定:通過使用cookie技術(shù)來維護應用的狀態(tài)。Cookie是可以被Web服務器設(shè)置的字符串,并且可以保存在瀏覽器中。當瀏覽器訪問了頁面1時,web服務器設(shè)置了一個cookie,并將這個cookie和頁面1一起返回給瀏覽器,瀏覽器接到cookie之后,就會保存起來,在它訪問頁面2的時候會把這個cookie也帶上,Web服務器接到請求時也能讀出cookie的值,根據(jù)cookie值的內(nèi)容就可以判斷和恢復一些用戶的信息狀態(tài)。Web-SSO完全可以利用Cookie技術(shù)來完成用戶登錄信息的保存,將瀏覽器中的Cookie和上文中的Ticket結(jié)合起來,完成SSO的功能。
SSO單點登錄
一個企業(yè)可能有很多個系統(tǒng),這些系統(tǒng)之間有一些關(guān)聯(lián)性,每個系統(tǒng)都有一個獨立的登錄模塊,但隨企業(yè)的發(fā)展,用到的系統(tǒng)可能越來越多,每次都要一個一個登錄你會越來越不方便, 單點登錄就應運而生 即 登錄其中的任意一個系統(tǒng),在其他的系統(tǒng)也達到登錄的狀態(tài)
它的解釋是:在多個應用系統(tǒng)中,只需要登錄一次,就可以訪問其他相互信任的應用系統(tǒng)。
如下圖,用戶要登錄Application1、Application2、Application3中的任意一個 都會跳轉(zhuǎn)到 SSO系統(tǒng),在SSO完成登錄,同時 其他系統(tǒng)也就完成登錄了。
普通的登錄機制
普通的登錄狀態(tài)是通過瀏覽器端的Cookie與服務器端的Session共同保證的,我們輸入用戶名密碼進行登錄,服務器會返回給瀏覽器一個Cookie(多組鍵值對組成),這個Cookie是這個用戶的唯一標識,同時在服務器端生成一個對應這個Cookie的Session,以后瀏覽器在對服務器進行請求時都會帶上這個Cookie,服務器收到請求后 會根據(jù)Cookie去找對應的Session,通過Session判斷用戶是不是登錄狀態(tài)
SSO實現(xiàn)機制
同域下的單點登錄
一個企業(yè)一般情況下只有一個域名,通過二級域名區(qū)分不同的系統(tǒng)。比如我們有個域名叫做:a.com,同時有兩個業(yè)務系統(tǒng)分別為:app1.a.com和app2.a.com。我們要做單點登錄(SSO),需要一個登錄系統(tǒng),叫做:sso.a.com。
我們只要在sso.a.com登錄,app1.a.com和app2.a.com就也登錄了。通過上面的登陸認證機制,我們可以知道,在sso.a.com中登錄了,其實是在sso.a.com的服務端的session中記錄了登錄狀態(tài),同時在瀏覽器端(Browser)的sso.a.com下寫入了Cookie。那么我們怎么才能讓app1.a.com和app2.a.com登錄呢?這里有兩個問題:
Cookie是不能跨域的,我們Cookie的domain屬性是sso.a.com,在給app1.a.com和app2.a.com發(fā)送請求是帶不上的。
sso、app1和app2是不同的應用,它們的session存在自己的應用內(nèi),是不共享的。
那么我們?nèi)绾谓鉀Q這兩個問題呢?針對第一個問題,sso登錄以后,可以將Cookie的域設(shè)置為頂域,即.a.com,這樣所有子域的系統(tǒng)都可以訪問到頂域的Cookie。我們在設(shè)置Cookie時,只能設(shè)置頂域和自己的域,不能設(shè)置其他的域。比如:我們不能在自己的系統(tǒng)中給baidu.com的域設(shè)置Cookie。
Cookie的問題解決了,我們再來看看session的問題。我們在sso系統(tǒng)登錄了,這時再訪問app1,Cookie也帶到了app1的服務端(Server),app1的服務端怎么找到這個Cookie對應的Session呢?這里就要把3個系統(tǒng)的Session共享,如圖所示。共享Session的解決方案有很多,例如:Spring-Session。這樣第2個問題也解決了。
同域下的單點登錄就實現(xiàn)了,但這還不是真正的單點登錄。
不同域下的單點登錄
同域下的單點登錄是巧用了Cookie頂域的特性。如果是不同域呢?不同域之間Cookie是不共享的,怎么辦?
這里我們就要說一說CAS流程了,這個流程是單點登錄的標準流程。
上圖是CAS官網(wǎng)上的標準流程,具體流程如下:
用戶訪問app系統(tǒng),app系統(tǒng)是需要登錄的,但用戶現(xiàn)在沒有登錄。
跳轉(zhuǎn)到CAS server,即SSO登錄系統(tǒng),以后圖中的CAS Server我們統(tǒng)一叫做SSO系統(tǒng)。 SSO系統(tǒng)也沒有登錄,彈出用戶登錄頁。
用戶填寫用戶名、密碼,SSO系統(tǒng)進行認證后,將登錄狀態(tài)寫入SSO的session,瀏覽器(Browser)中寫入SSO域下的Cookie。
SSO系統(tǒng)登錄完成后會生成一個ST(Service Ticket),然后跳轉(zhuǎn)到app系統(tǒng),同時將ST作為參數(shù)傳遞給app系統(tǒng)。
app系統(tǒng)拿到ST后,從后臺向SSO發(fā)送請求,驗證ST是否有效。
驗證通過后,app系統(tǒng)將登錄狀態(tài)寫入session并設(shè)置app域下的Cookie。
至此,跨域單點登錄就完成了。以后我們再訪問app系統(tǒng)時,app就是登錄的。接下來,我們再看看訪問app2系統(tǒng)時的流程。
用戶訪問app2系統(tǒng),app2系統(tǒng)沒有登錄,跳轉(zhuǎn)到SSO。
由于SSO已經(jīng)登錄了,不需要重新登錄認證。
SSO生成ST,瀏覽器跳轉(zhuǎn)到app2系統(tǒng),并將ST作為參數(shù)傳遞給app2。
app2拿到ST,后臺訪問SSO,驗證ST是否有效。
驗證成功后,app2將登錄狀態(tài)寫入session,并在app2域下寫入Cookie。
這樣,app2系統(tǒng)不需要走登錄流程,就已經(jīng)是登錄了。SSO,app和app2在不同的域,它們之間的session不共享也是沒問題的。
有人就會想,SSO系統(tǒng)登錄后,跳回原業(yè)務系統(tǒng)時,帶了個參數(shù)ST,業(yè)務系統(tǒng)還要拿ST再次訪問SSO進行驗證,覺得這個步驟有點多余。他想SSO登錄認證通過后,通過回調(diào)地址將用戶信息返回給原業(yè)務系統(tǒng),原業(yè)務系統(tǒng)直接設(shè)置登錄狀態(tài),這樣流程簡單,也完成了登錄,不是很好嗎?
其實這樣問題時很嚴重的,如果我在SSO沒有登錄,而是直接在瀏覽器中敲入回調(diào)的地址,并帶上偽造的用戶信息,是不是業(yè)務系統(tǒng)也認為登錄了呢?這是很可怕的。單點登錄,資源都在各個業(yè)務系統(tǒng)這邊,不在SSO那一方。 用戶在給SSO服務器提供了用戶名密碼后,作為業(yè)務系統(tǒng)并不知道這件事。 SSO隨便給業(yè)務系統(tǒng)一個ST,那么業(yè)務系統(tǒng)是不能確定這個ST是用戶偽造的,還是真的有效,所以要拿著這個ST去SSO服務器再問一下,這個用戶給我的ST是否有效,是有效的我才能讓這個用戶訪問。