互聯(lián)網(wǎng)/程序員/技術(shù)/資料共享?
https://muyinchen.github.io注:?jiǎn)吸c(diǎn)登錄原理是一個(gè)重要知識(shí)點(diǎn),也常被問(wèn)及,很多童鞋照葫蘆畫(huà)瓢搭建過(guò)單點(diǎn)登錄,但是被問(wèn)到原理時(shí)可能說(shuō)不出來(lái),下面簡(jiǎn)單介紹,拋磚引玉,希望對(duì)大家有所幫助。單點(diǎn)登錄在現(xiàn)在的系統(tǒng)架構(gòu)中廣泛存在,他將多個(gè)子系統(tǒng)的認(rèn)證體系打通,實(shí)現(xiàn)了一個(gè)入口多處使用,而在架構(gòu)單點(diǎn)登錄時(shí),也會(huì)遇到一些小問(wèn)題,在不同的應(yīng)用環(huán)境中可以采用不同的單點(diǎn)登錄實(shí)現(xiàn)方案來(lái)滿(mǎn)足需求。我將以我所遇到的應(yīng)用環(huán)境以及在其中所經(jīng)歷的各個(gè)階段與大家分享,若有不足,希望各位不吝賜教。一、共享Session
共享Session可謂是實(shí)現(xiàn)單點(diǎn)登錄最直接、最簡(jiǎn)單的方式。將用戶(hù)認(rèn)證信息保存于Session中,即以Session內(nèi)存儲(chǔ)的值為用戶(hù)憑證,這在單個(gè)站點(diǎn)內(nèi)使用是很正常也很容易實(shí)現(xiàn)的,而在用戶(hù)驗(yàn)證、用戶(hù)信息管理與業(yè)務(wù)應(yīng)用分離的場(chǎng)景下即會(huì)遇到單點(diǎn)登錄的問(wèn)題,在應(yīng)用體系簡(jiǎn)單,子系統(tǒng)很少的情況下,可以考慮采用Session共享的方法來(lái)處理這個(gè)問(wèn)題。這個(gè)架構(gòu)我使用了基于Redis的Session共享方案。將Session存儲(chǔ)于Redis上,然后將整個(gè)系統(tǒng)的全局Cookie Domain設(shè)置于頂級(jí)域名上,這樣SessionID就能在各個(gè)子系統(tǒng)間共享。這個(gè)方案存在著嚴(yán)重的擴(kuò)展性問(wèn)題,首先,ASP.NET的Session存儲(chǔ)必須為SessionStateItemCollection對(duì)象,而存儲(chǔ)的結(jié)構(gòu)是經(jīng)過(guò)序列化后經(jīng)過(guò)加密存儲(chǔ)的。并且當(dāng)用戶(hù)訪問(wèn)應(yīng)用時(shí),他首先做的就是將存儲(chǔ)容器里的所有內(nèi)容全部取出,并且反序列化為SessionStateItemCollection對(duì)象。這就決定了他具有以下約束:二、基于OpenId的單點(diǎn)登錄
這種單點(diǎn)登錄將用戶(hù)的身份標(biāo)識(shí)信息簡(jiǎn)化為OpenId存放于客戶(hù)端,當(dāng)用戶(hù)登錄某個(gè)子系統(tǒng)時(shí),將OpenId傳送到服務(wù)端,服務(wù)端根據(jù)OpenId構(gòu)造用戶(hù)驗(yàn)證信息,多用于C/S與B/S相結(jié)合的系統(tǒng),流程如下:由上圖可以看到,這套單點(diǎn)登錄依賴(lài)于OpenId的傳遞,其驗(yàn)證的基礎(chǔ)在于OpenId的存儲(chǔ)以及發(fā)送。當(dāng)用戶(hù)第一次登錄時(shí),將用戶(hù)名密碼發(fā)送給驗(yàn)證服務(wù);
驗(yàn)證服務(wù)將用戶(hù)標(biāo)識(shí)OpenId返回到客戶(hù)端;
客戶(hù)端進(jìn)行存儲(chǔ);
訪問(wèn)子系統(tǒng)時(shí),將OpenId發(fā)送到子系統(tǒng);
子系統(tǒng)將OpenId轉(zhuǎn)發(fā)到驗(yàn)證服務(wù);
驗(yàn)證服務(wù)將用戶(hù)認(rèn)證信息返回給子系統(tǒng);
子系統(tǒng)構(gòu)建用戶(hù)驗(yàn)證信息后將授權(quán)后的內(nèi)容返回給客戶(hù)端。
這套單點(diǎn)登錄驗(yàn)證機(jī)制的主要問(wèn)題在于他基于C/S架構(gòu)下將用戶(hù)的OpenId存儲(chǔ)于客戶(hù)端,在子系統(tǒng)之間發(fā)送OpenId,而B(niǎo)/S模式下要做到這一點(diǎn)就顯得較為困難。為了處理這個(gè)問(wèn)題我們將引出下一種方式,這種方式將解決B/S模式下的OpenId的存儲(chǔ)、傳遞問(wèn)題。三、基于Cookie的OpenId存儲(chǔ)方案
我們知道,Cookie的作用在于充當(dāng)一個(gè)信息載體在Server端和Browser端進(jìn)行信息傳遞,而Cookie一般是以域名為分割的,例如a.xxx.com與b.xxx.com的Cookie是不能互相訪問(wèn)的,但是子域名是可以訪問(wèn)上級(jí)域名的Cookie的。即a.xxx.com和b.xxx.com是可以訪問(wèn)xxx.com下的Cookie的,于是就能將頂級(jí)域名的Cookie作為OpenId的載體。驗(yàn)證步驟和上第二個(gè)方法非常相似:在提供驗(yàn)證服務(wù)的站點(diǎn)里登錄;
將OpenId寫(xiě)入頂級(jí)域名Cookie里;
訪問(wèn)子系統(tǒng)(Cookie里帶有OpenId)
子系統(tǒng)取出OpenId通過(guò)并向驗(yàn)證服務(wù)發(fā)送OpenId
返回用戶(hù)認(rèn)證信息
返回授權(quán)后的內(nèi)容
在以上兩種方法中我們都可以看到通過(guò)OpenId解耦了Session共享方案中的類(lèi)型等問(wèn)題,并且構(gòu)造用戶(hù)驗(yàn)證信息將更靈活,子系統(tǒng)間的驗(yàn)證是相互獨(dú)立的,但是在第三種方案里,我們基于所有子系統(tǒng)都是同一個(gè)頂級(jí)域名的假設(shè),而在實(shí)際生產(chǎn)環(huán)境里有多個(gè)域名是很正常的事情,那么就不得不考慮跨域問(wèn)題究竟如何解決。四、B/S多域名環(huán)境下的單點(diǎn)登錄處理
在多個(gè)頂級(jí)域名的情況下,我們將無(wú)法讓各個(gè)子系統(tǒng)的OpenId共享。處理B/S環(huán)境下的跨域問(wèn)題,我們首先就應(yīng)該想到JSONP的方案。用戶(hù)通過(guò)登錄子系統(tǒng)進(jìn)行用戶(hù)登錄;
用戶(hù)登錄子系統(tǒng)記錄了用戶(hù)的登錄狀態(tài)、OpenId等信息;
用戶(hù)使用業(yè)務(wù)子系統(tǒng);
若用戶(hù)未登錄業(yè)務(wù)子系統(tǒng)則將用戶(hù)跳轉(zhuǎn)至用戶(hù)登錄子系統(tǒng);
用戶(hù)子系統(tǒng)通過(guò)JSONP接口將用戶(hù)OpenId傳給業(yè)務(wù)子系統(tǒng);
業(yè)務(wù)子系統(tǒng)通過(guò)OpenId調(diào)用驗(yàn)證服務(wù);
驗(yàn)證服務(wù)返回認(rèn)證信息、業(yè)務(wù)子系統(tǒng)構(gòu)造用戶(hù)登錄憑證;(此時(shí)用戶(hù)客戶(hù)端已經(jīng)與子業(yè)務(wù)系統(tǒng)的驗(yàn)證信息已經(jīng)一一對(duì)應(yīng))
將用戶(hù)登錄結(jié)果返回用戶(hù)登錄子系統(tǒng),若成功登錄則將用戶(hù)跳轉(zhuǎn)回業(yè)務(wù)子系統(tǒng);
將授權(quán)后的內(nèi)容返回客戶(hù)端;
五、安全問(wèn)題
經(jīng)過(guò)以上步驟,跨域情況下的單點(diǎn)登錄問(wèn)題已經(jīng)可以得到解決。而在整個(gè)開(kāi)發(fā)過(guò)程初期,我們采用用戶(hù)表中記錄一個(gè)OpenId字段來(lái)保存用戶(hù)OpenId,而這個(gè)機(jī)制下很明顯存在一些安全性、擴(kuò)展性問(wèn)題。這個(gè)擴(kuò)展性問(wèn)題主要體現(xiàn)在一個(gè)方面:OpenId的安全性和用戶(hù)體驗(yàn)的矛盾。整個(gè)單點(diǎn)登錄的機(jī)制決定了OpenId是會(huì)出現(xiàn)在客戶(hù)端的,所以O(shè)penId需要有過(guò)期機(jī)制,假如用戶(hù)在一個(gè)終端登錄的話(huà)可以選擇在用戶(hù)每次登錄或者每次退出時(shí)刷新OpenId,而在多終端登錄的情況下就會(huì)出現(xiàn)矛盾:當(dāng)一個(gè)終端刷新了OpenId之后其他終端將無(wú)法正常授權(quán)。而最終,我采用了單用戶(hù)多OpenId的解決方案。每次用戶(hù)通過(guò)用戶(hù)名/密碼登錄時(shí),產(chǎn)生一個(gè)OpenId保存在Redis里,并且設(shè)定過(guò)期時(shí)間,這樣多個(gè)終端登錄就會(huì)有多個(gè)OpenId與之對(duì)應(yīng),不再會(huì)存在一個(gè)OpenId失效所有終端驗(yàn)證都失效的情況。推薦閱讀:
【11期】分布式系統(tǒng)接口,如何避免表單的重復(fù)提交?
【10期】Redis 面試常見(jiàn)問(wèn)答
【09期】說(shuō)說(shuō)hashCode() 和 equals() 之間的關(guān)系?
5T技術(shù)資源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,單片機(jī),樹(shù)莓派,等等。在公眾號(hào)內(nèi)回復(fù)「2048」,即可免費(fèi)獲?。?!微信掃描二維碼,關(guān)注我的公眾號(hào)
朕已閱?