什么是單點(diǎn)登錄?
單點(diǎn)登錄(Single Sign On,簡稱SSO)
背景:
以前的時(shí)候,一般我們就單系統(tǒng),所有的功能都在同一個(gè)系統(tǒng)上。
后來,我們?yōu)榱撕侠砝觅Y源和降低耦合性,于是把單系統(tǒng)拆分成多個(gè)子系統(tǒng)。比如阿里系的淘寶和天貓,很明顯地我們可以知道這是兩個(gè)系統(tǒng),但是你在使用的時(shí)候,登錄了天貓,淘寶也會(huì)自動(dòng)登錄。

如圖所示,圖中有4個(gè)系統(tǒng),分別是Application1、Application2、Application3、和SSO。Application1、Application2、Application3沒有登錄模塊,而SSO只有登錄模塊,沒有其他的業(yè)務(wù)模塊,當(dāng)Application1、Application2、Application3需要登錄時(shí),將跳到SSO系統(tǒng),SSO系統(tǒng)完成登錄,其他的應(yīng)用系統(tǒng)也就隨之登錄了。這完全符合我們對(duì)單點(diǎn)登錄(SSO)的定義。
簡單來說,單點(diǎn)登錄就是在多個(gè)系統(tǒng)中,用戶只需一次登錄,各個(gè)系統(tǒng)即可感知該用戶已經(jīng)登錄。
單點(diǎn)登錄的來源:
1、早期web單系統(tǒng)應(yīng)用:
早期web單系統(tǒng)應(yīng)用,用戶的登錄以及權(quán)限就顯得十分簡單,當(dāng)瀏覽器向服務(wù)器發(fā)送登錄請(qǐng)求時(shí),驗(yàn)證通過之后,會(huì)將用戶信息存入seesion中,然后服務(wù)器會(huì)生成一個(gè)sessionId放入cookie中,隨后返回給瀏覽器。

驗(yàn)證登錄的這個(gè)會(huì)話就是session,維護(hù)了用戶狀態(tài),也就是所謂的HTTP有狀態(tài)協(xié)議,我們經(jīng)常可以在瀏覽器中看到JSESSIONID,這個(gè)就是用來維持這個(gè)關(guān)系的key。
2、分布式集群部署:
由于網(wǎng)站的訪問量越來也大,單機(jī)部署已經(jīng)是巨大瓶頸,所以才有了后來的分布式集群部署。如果引入集群的概念,單應(yīng)用可能重新部署在3臺(tái)tomcat以上服務(wù)器,使用nginx來實(shí)現(xiàn)反向代理。
但是增加新的服務(wù)器之后,不同的服務(wù)器之間的sessionId是不一樣的,可能在A服務(wù)器上已經(jīng)登錄成功了,能從服務(wù)器的session中獲取用戶信息,但是在B服務(wù)器上卻查不到session信息,只好退出來繼續(xù)登錄,結(jié)果A服務(wù)器中的session因?yàn)槌瑫r(shí)失效,登錄之后又被強(qiáng)制退出來要求重新登錄。
所以不得不考慮多服務(wù)器之間的session數(shù)據(jù)一致的問題,這就是單點(diǎn)登錄的最早來源。

單點(diǎn)登錄技術(shù)實(shí)現(xiàn):
單點(diǎn)登錄的本質(zhì)就是在多個(gè)應(yīng)用系統(tǒng)中共享登錄狀態(tài),如果用戶的登錄狀態(tài)是記錄在 Session 中的,要實(shí)現(xiàn)共享登錄狀態(tài),就要先共享 Session。
所以實(shí)現(xiàn)單點(diǎn)登錄的關(guān)鍵在于,如何讓 Session ID(或 Token)在多個(gè)域中共享。
1、同域下的單點(diǎn)登錄:
一個(gè)企業(yè)一般情況下只有一個(gè)域名,通過二級(jí)域名區(qū)分不同的系統(tǒng)。比如我們有個(gè)域名叫做:a.com,同時(shí)有兩個(gè)業(yè)務(wù)系統(tǒng)分別為:app1.a.com和app2.a.com。我們要做單點(diǎn)登錄(SSO),需要一個(gè)登錄系統(tǒng),叫做:sso.a.com。
實(shí)現(xiàn)方式:
在sso.a.com中登錄了,其實(shí)是在sso.a.com的服務(wù)端的session中記錄了登錄狀態(tài),同時(shí)在瀏覽器端(Browser)的sso.a.com下寫入了Cookie。那么我們?cè)趺床拍茏宎pp1.a.com和app2.a.com登錄呢?這里有兩個(gè)問題:
Cookie是不能跨域的,我們Cookie的domain屬性是sso.a.com,在給app1.a.com和app2.a.com發(fā)送請(qǐng)求是帶不上的。
sso、app1和app2是不同的應(yīng)用,它們的session存在自己的應(yīng)用內(nèi),是不共享的。
那么我們?nèi)绾谓鉀Q這兩個(gè)問題呢?
sso登錄以后,可以將Cookie的 domian 域設(shè)置為頂域,即.a.com,這樣所有子域的系統(tǒng)都可以訪問到頂域的Cookie。在設(shè)置Cookie時(shí),只能設(shè)置頂域和自己的域,不能設(shè)置其他的域。
把3個(gè)系統(tǒng)的Session共享,共享Session的解決方案有很多,例如:Spring-Session

2、跨域下的單點(diǎn)登錄
如果是不同域呢?不同域之間Cookie是不共享的,怎么辦?
這里我們就要說一說CAS流程了,這個(gè)流程是單點(diǎn)登錄的標(biāo)準(zhǔn)流程。
具體流程如下:
1)用戶訪問app系統(tǒng),app系統(tǒng)是需要登錄的,但用戶現(xiàn)在沒有登錄。
2)跳轉(zhuǎn)到CAS server,即SSO登錄系統(tǒng),以后圖中的CAS Server我們統(tǒng)一叫做SSO系統(tǒng)。 SSO系統(tǒng)也沒有登錄,彈出用戶登錄頁。
3)用戶填寫用戶名、密碼,SSO系統(tǒng)進(jìn)行認(rèn)證后,將登錄狀態(tài)寫入SSO的session,瀏覽器(Browser)中寫入SSO域下的Cookie。
4)SSO系統(tǒng)登錄完成后會(huì)生成一個(gè)ST(Service Ticket),然后跳轉(zhuǎn)到app系統(tǒng),同時(shí)將ST作為參數(shù)傳遞給app系統(tǒng)。
5)app系統(tǒng)拿到ST后,從后臺(tái)向SSO發(fā)送請(qǐng)求,驗(yàn)證ST是否有效。
6)驗(yàn)證通過后,app系統(tǒng)將登錄狀態(tài)寫入session并設(shè)置app域下的Cookie。
至此,跨域單點(diǎn)登錄就完成了。以后我們?cè)僭L問app系統(tǒng)時(shí),app就是登錄的。接下來,我們?cè)倏纯丛L問app2系統(tǒng)時(shí)的流程。
1)用戶訪問app2系統(tǒng),app2系統(tǒng)沒有登錄,跳轉(zhuǎn)到SSO。
2)由于SSO已經(jīng)登錄了,不需要重新登錄認(rèn)證。
3)SSO生成ST,瀏覽器跳轉(zhuǎn)到app2系統(tǒng),并將ST作為參數(shù)傳遞給app2。
4)app2拿到ST,后臺(tái)訪問SSO,驗(yàn)證ST是否有效。
5)驗(yàn)證成功后,app2將登錄狀態(tài)寫入session,并在app2域下寫入Cookie。
這樣,app2系統(tǒng)不需要走登錄流程,就已經(jīng)是登錄了。SSO,app和app2在不同的域,它們之間的session不共享也是沒問題的。
Cookie的屬性詳細(xì)介紹:
name 名稱,一旦創(chuàng)建,名稱便不可更改
value 值,如果值為Unicode字符,需要為字符編碼。如果值為二進(jìn)制數(shù)據(jù),則需要使用BASE64編碼
maxAge 失效的時(shí)間,單位秒。正數(shù),則該Cookie在maxAge秒之后失效。如果為負(fù)數(shù),該Cookie為臨時(shí)Cookie,關(guān)閉瀏覽器即失效,瀏覽器也不會(huì)以任何形式保存該Cookie。如果為0,表示刪除該Cookie。默認(rèn)為-1。
signed 所請(qǐng)求的cookie應(yīng)該被簽名
expires cookie 過期的 Date
path cookie 路徑, 如果設(shè)置為“/sessionWeb/”,則只有contextPath為“/sessionWeb”的程序可以訪問該Cookie。如果設(shè)置為“/”,則本域名下contextPath都可以訪問該Cookie。注意最后一個(gè)字符必須為“/”。默認(rèn)是’/’,
domain cookie 域名。如果設(shè)置為“.google.com”,則所有以“google.com”結(jié)尾的域名都可以訪問該Cookie。注意第一個(gè)字符必須為“.”。
secure 是否僅被使用安全協(xié)議傳輸。安全協(xié)議。安全協(xié)議有HTTPS,SSL等,在網(wǎng)絡(luò)上傳輸數(shù)據(jù)之前先將數(shù)據(jù)加密。默認(rèn)為false。
httpOnly 設(shè)置為true,則服務(wù)器可訪問 cookie, 瀏覽器js腳本將無法讀取到cookie信息,這樣能有效的防止XSS攻擊。默認(rèn)是 true
overwrite 一個(gè)布爾值,表示是否覆蓋以前設(shè)置的同名的 cookie (默認(rèn)是 false). 如果是 true, 在同一個(gè)請(qǐng)求中設(shè)置相同名稱的所有 Cookie(不管路徑或域)是否在設(shè)置此Cookie 時(shí)從 Set-Cookie 消息頭中過濾掉。
comment 用處說明
更多開發(fā)細(xì)節(jié)說明:
從客戶端讀取Cookie時(shí),包括maxAge在內(nèi)的其他屬性都是不可讀的,也不會(huì)被提交。瀏覽器提交Cookie時(shí)只會(huì)提交name與value屬性。maxAge屬性只被瀏覽器用來判斷Cookie是否過期。
Cookie的修改、刪除
Cookie并不提供修改、刪除操作。如果要修改某個(gè)Cookie,只需要新建一個(gè)同名的Cookie,添加到response中覆蓋原來的Cookie。
注意:修改、刪除Cookie時(shí),新建的Cookie除value、maxAge之外的所有屬性,例如name、path、domain等,都要與原Cookie完全一樣。否則,瀏覽器將視為兩個(gè)不同的Cookie不予覆蓋,導(dǎo)致修改、刪除失敗。
————————————————
版權(quán)聲明:本文為CSDN博主「落花見流水」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_41913971/article/details/122609233
浙公網(wǎng)安備 33010602011771號(hào)