單點(diǎn)登錄的實(shí)現(xiàn)原理

image.png

單點(diǎn)登錄在現(xiàn)在的系統(tǒng)架構(gòu)中廣泛存在,他將多個(gè)子系統(tǒng)的認(rèn)證體系打通,實(shí)現(xiàn)了一個(gè)入口多處使用麦牺,而在架構(gòu)單點(diǎn)登錄時(shí),也會遇到一些小問題鞭缭,在不同的應(yīng)用環(huán)境中可以采用不同的單點(diǎn)登錄實(shí)現(xiàn)方案來滿足需求剖膳。我將以我所遇到的應(yīng)用環(huán)境以及在其中所經(jīng)歷的各個(gè)階段與大家分享,若有不足岭辣,希望各位不吝賜教吱晒。

一、共享Session

共享Session可謂是實(shí)現(xiàn)單點(diǎn)登錄最直接沦童、最簡單的方式仑濒。將用戶認(rèn)證信息保存于Session中叹话,即以Session內(nèi)存儲的值為用戶憑證,這在單個(gè)站點(diǎn)內(nèi)使用是很正常也很容易實(shí)現(xiàn)的墩瞳,而在用戶驗(yàn)證驼壶、用戶信息管理與業(yè)務(wù)應(yīng)用分離的場景下即會遇到單點(diǎn)登錄的問題,在應(yīng)用體系簡單喉酌,子系統(tǒng)很少的情況下热凹,可以考慮采用Session共享的方法來處理這個(gè)問題。
image.png

這個(gè)架構(gòu)我使用了基于Redis的Session共享方案泪电。將Session存儲于Redis上般妙,然后將整個(gè)系統(tǒng)的全局Cookie Domain設(shè)置于頂級域名上,這樣SessionID就能在各個(gè)子系統(tǒng)間共享相速。
這個(gè)方案存在著嚴(yán)重的擴(kuò)展性問題碟渺,首先,ASP.NET的Session存儲必須為SessionStateItemCollection對象突诬,而存儲的結(jié)構(gòu)是經(jīng)過序列化后經(jīng)過加密存儲的苫拍。并且當(dāng)用戶訪問應(yīng)用時(shí),他首先做的就是將存儲容器里的所有內(nèi)容全部取出攒霹,并且反序列化為SessionStateItemCollection對象怯疤。這就決定了他具有以下約束:

  1. Session中所涉及的類型必須是子系統(tǒng)中共同擁有的(即程序集、類型都需要一致)催束,這導(dǎo)致Session的使用受到諸多限制集峦;
  2. 跨頂級域名的情況完全無法處理;

二抠刺、基于OpenId的單點(diǎn)登錄

這種單點(diǎn)登錄將用戶的身份標(biāo)識信息簡化為OpenId存放于客戶端塔淤,當(dāng)用戶登錄某個(gè)子系統(tǒng)時(shí),將OpenId傳送到服務(wù)端速妖,服務(wù)端根據(jù)OpenId構(gòu)造用戶驗(yàn)證信息高蜂,多用于C/S與B/S相結(jié)合的系統(tǒng),流程如下:
image.png

由上圖可以看到罕容,這套單點(diǎn)登錄依賴于OpenId的傳遞备恤,其驗(yàn)證的基礎(chǔ)在于OpenId的存儲以及發(fā)送。

  1. 當(dāng)用戶第一次登錄時(shí)锦秒,將用戶名密碼發(fā)送給驗(yàn)證服務(wù)露泊;
  2. 驗(yàn)證服務(wù)將用戶標(biāo)識OpenId返回到客戶端;
  3. 客戶端進(jìn)行存儲旅择;
  4. 訪問子系統(tǒng)時(shí)惭笑,將OpenId發(fā)送到子系統(tǒng);
  5. 子系統(tǒng)將OpenId轉(zhuǎn)發(fā)到驗(yàn)證服務(wù);
  6. 驗(yàn)證服務(wù)將用戶認(rèn)證信息返回給子系統(tǒng)沉噩;
  7. 子系統(tǒng)構(gòu)建用戶驗(yàn)證信息后將授權(quán)后的內(nèi)容返回給客戶端捺宗。
    這套單點(diǎn)登錄驗(yàn)證機(jī)制的主要問題在于他基于C/S架構(gòu)下將用戶的OpenId存儲于客戶端,在子系統(tǒng)之間發(fā)送OpenId川蒙,而B/S模式下要做到這一點(diǎn)就顯得較為困難蚜厉。為了處理這個(gè)問題我們將引出下一種方式,這種方式將解決B/S模式下的OpenId的存儲派歌、傳遞問題弯囊。

三、基于Cookie的OpenId存儲方案

我們知道胶果,Cookie的作用在于充當(dāng)一個(gè)信息載體在Server端和Browser端進(jìn)行信息傳遞,而Cookie一般是以域名為分割的斤斧,例如a.xxx.com與b.xxx.com的Cookie是不能互相訪問的早抠,但是子域名是可以訪問上級域名的Cookie的。即a.xxx.com和b.xxx.com是可以訪問xxx.com下的Cookie的撬讽,于是就能將頂級域名的Cookie作為OpenId的載體蕊连。
image.png

驗(yàn)證步驟和上第二個(gè)方法非常相似:

  1. 在提供驗(yàn)證服務(wù)的站點(diǎn)里登錄;
  2. 將OpenId寫入頂級域名Cookie里游昼;
  3. 訪問子系統(tǒng)(Cookie里帶有OpenId)
  4. 子系統(tǒng)取出OpenId通過并向驗(yàn)證服務(wù)發(fā)送OpenId
  5. 返回用戶認(rèn)證信息
  6. 返回授權(quán)后的內(nèi)容
    在以上兩種方法中我們都可以看到通過OpenId解耦了Session共享方案中的類型等問題甘苍,并且構(gòu)造用戶驗(yàn)證信息將更靈活,子系統(tǒng)間的驗(yàn)證是相互獨(dú)立的烘豌,但是在第三種方案里载庭,我們基于所有子系統(tǒng)都是同一個(gè)頂級域名的假設(shè),而在實(shí)際生產(chǎn)環(huán)境里有多個(gè)域名是很正常的事情廊佩,那么就不得不考慮跨域問題究竟如何解決囚聚。

四、B/S多域名環(huán)境下的單點(diǎn)登錄處理

在多個(gè)頂級域名的情況下标锄,我們將無法讓各個(gè)子系統(tǒng)的OpenId共享顽铸。處理B/S環(huán)境下的跨域問題,我們首先就應(yīng)該想到JSONP的方案料皇。
image.png

驗(yàn)證步驟如下:

  1. 用戶通過登錄子系統(tǒng)進(jìn)行用戶登錄谓松;
  2. 用戶登錄子系統(tǒng)記錄了用戶的登錄狀態(tài)、OpenId等信息践剂;
  3. 用戶使用業(yè)務(wù)子系統(tǒng)鬼譬;
  4. 若用戶未登錄業(yè)務(wù)子系統(tǒng)則將用戶跳轉(zhuǎn)至用戶登錄子系統(tǒng);
  5. 用戶子系統(tǒng)通過JSONP接口將用戶OpenId傳給業(yè)務(wù)子系統(tǒng)舷手;
  6. 業(yè)務(wù)子系統(tǒng)通過OpenId調(diào)用驗(yàn)證服務(wù)拧簸;
  7. 驗(yàn)證服務(wù)返回認(rèn)證信息、業(yè)務(wù)子系統(tǒng)構(gòu)造用戶登錄憑證男窟;(此時(shí)用戶客戶端已經(jīng)與子業(yè)務(wù)系統(tǒng)的驗(yàn)證信息已經(jīng)一一對應(yīng))
  8. 將用戶登錄結(jié)果返回用戶登錄子系統(tǒng)盆赤,若成功登錄則將用戶跳轉(zhuǎn)回業(yè)務(wù)子系統(tǒng)贾富;
  9. 將授權(quán)后的內(nèi)容返回客戶端;

五牺六、安全問題

經(jīng)過以上步驟颤枪,跨域情況下的單點(diǎn)登錄問題已經(jīng)可以得到解決。而在整個(gè)開發(fā)過程初期淑际,我們采用用戶表中紀(jì)錄一個(gè)OpenId字段來保存用戶OpenId畏纲,而這個(gè)機(jī)制下很明顯存在一些安全性、擴(kuò)展性問題春缕。這個(gè)擴(kuò)展性問題主要體現(xiàn)在一個(gè)方面:OpenId的安全性和用戶體驗(yàn)的矛盾盗胀。
整個(gè)單點(diǎn)登錄的機(jī)制決定了OpenId是會出現(xiàn)在客戶端的,所以O(shè)penId需要有過期機(jī)制锄贼,假如用戶在一個(gè)終端登錄的話可以選擇在用戶每次登錄或者每次退出時(shí)刷新OpenId票灰,而在多終端登錄的情況下就會出現(xiàn)矛盾:當(dāng)一個(gè)終端刷新了OpenId之后其他終端將無法正常授權(quán)。而最終宅荤,我采用了單用戶多OpenId的解決方案屑迂。每次用戶通過用戶名/密碼登錄時(shí),產(chǎn)生一個(gè)OpenId保存在Redis里冯键,并且設(shè)定過期時(shí)間惹盼,這樣多個(gè)終端登錄就會有多個(gè)OpenId與之對應(yīng),不再會存在一個(gè)OpenId失效所有終端驗(yàn)證都失效的情況惫确。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末手报,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子雕薪,更是在濱河造成了極大的恐慌昧诱,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件所袁,死亡現(xiàn)場離奇詭異盏档,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)燥爷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門蜈亩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人前翎,你說我怎么就攤上這事稚配。” “怎么了港华?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵道川,是天一觀的道長。 經(jīng)常有香客問我,道長冒萄,這世上最難降的妖魔是什么臊岸? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮尊流,結(jié)果婚禮上帅戒,老公的妹妹穿的比我還像新娘。我一直安慰自己崖技,他們只是感情好逻住,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著迎献,像睡著了一般瞎访。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上忿晕,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天装诡,我揣著相機(jī)與錄音,去河邊找鬼践盼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛宾巍,可吹牛的內(nèi)容都是我干的咕幻。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼顶霞,長吁一口氣:“原來是場噩夢啊……” “哼肄程!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起选浑,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤蓝厌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后古徒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拓提,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年隧膘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了代态。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡疹吃,死狀恐怖蹦疑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情萨驶,我是刑警寧澤歉摧,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響叁温,放射性物質(zhì)發(fā)生泄漏再悼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一券盅、第九天 我趴在偏房一處隱蔽的房頂上張望帮哈。 院中可真熱鬧,春花似錦锰镀、人聲如沸娘侍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽憾筏。三九已至,卻和暖如春花鹅,著一層夾襖步出監(jiān)牢的瞬間氧腰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工刨肃, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留古拴,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓真友,卻偏偏與公主長得像黄痪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子盔然,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容