這段時間出于大產(chǎn)品集成贝润,我們嘗試實現(xiàn)了系統(tǒng)認證從jwt到SAML的改造积糯,以完成跨域免密登陸的功能掂墓。組里的小朋友單槍匹馬完成了新功能,這里還是要夸贊一番的看成。今天借此機會談?wù)凷AML2.0的原理君编,并簡單介紹一下單點登陸。
Token
首先我們從Token講起川慌。Token一般翻譯成令牌或是憑證吃嘿,指訪問資源時用的憑據(jù)。現(xiàn)代應(yīng)用一般都是秉承前后端分離的原則梦重,當前端向后端請求API時兑燥,需要有一個token來證明其合法性。這個token一般是通過用戶名/密碼獲取的琴拧;Token既可以是后端賦予的降瞳,也可以來自后端信任的第三方服務(wù)器。這里提到的SAML就是所謂的由三方服務(wù)提供得到的憑據(jù)蚓胸。
此外力崇,攜帶token的方式也不一而足,可以通過HTTP Header赢织,或是URL參數(shù)亮靴,或是其他自定義的映射方式。通常token是有期限于置,過期了需要再次請求token茧吊,最常見的方式自然是重新登錄贞岭;當然也有些設(shè)計會將token更細分為access token和refresh token,access token用于資源請求搓侄,refresh token用于更新access token瞄桨。這個不是本期的重點,就一筆帶過了讶踪。
SSO(Single sign-on)
介紹完Token知識芯侥,再說說單點登陸。通常公里內(nèi)部會有非常多的工具平臺供大家使用乳讥,比如郵箱柱查、考勤、公告欄云石、日程等等唉工。一般來說這些平臺都是獨立設(shè)計實現(xiàn)的,系統(tǒng)設(shè)計千差萬別汹忠,但用戶系統(tǒng)基本都是必備的淋硝。不過假如每個系統(tǒng)都獨自實現(xiàn)一套具有登陸認證的用戶體系,使用起來必然很不方便宽菜。所以比較現(xiàn)實的設(shè)計就是共用一套用戶體系谣膳,只要用戶在這一處登陸后就可以訪問所有資源。這就是所謂的單點登陸(SSO)铅乡。
SSO是所有這套用戶共用系統(tǒng)的統(tǒng)稱参歹,具體設(shè)計現(xiàn)在比較常見的有:SAML2.0、OAuth2.0隆判。優(yōu)劣我不在這里比較了犬庇,反正我廠選擇的正是SAML2.0。
SAML(Security Assertion Markup Language)
進入主題前侨嘀,再提兩個SSO的概念:
-
IDP (Identity Provider)
也有稱作Authorization Server的臭挽,顧名思義,提供認證的服務(wù)器
-
SP(Service Provider)
也有的地方叫Resource Server——資源服務(wù)器咬腕。
SAML翻譯過來叫做安全斷言標記語言欢峰,用來在安全域中交換身份,驗證數(shù)據(jù)和授權(quán)數(shù)據(jù)涨共;通俗來說纽帖,就是通過Token在SP和IDP之間傳遞用戶信息和訪問權(quán)限。下面是SAML的具體流程圖举反,大家可以在圖里體會一下IDP和SP懊直,這里sp.com是資源網(wǎng)站,sso.com是認證網(wǎng)站:
具體細節(jié)各個公司在實現(xiàn)上會有細微的差別火鼻,但基本流程大致是相同的:
瀏覽器(sp.com)發(fā)起首次資源請求
SP根據(jù)請求來源室囊,向IDP獲取SAML的descriptor雕崩,這里會包含credentials, loginURL等等信息(注:這一步也可以省略,信息通常已存儲在SP中)
SP隨后將Browser重定向到登錄頁面(sso.com)融撞,同時會攜帶一些表單信息盼铁;這些信息主要包含在URL的query中
然后用戶輸入ID/密碼,并將表單發(fā)送給IDP
IDP驗證成功后尝偎,再將瀏覽器重定向回sp.com饶火,并在body里攜帶一個包含用戶信息的SAML Token(一個非常巨大的XML)
之后瀏覽器就會向SP發(fā)送
/assert
請求,將SAML Token送去后端驗證-
SP就根據(jù)步驟2中拿到的descriptor致扯,驗證這次token合法性肤寝,并從中解密出用戶信息以及過期時間。驗證成功后急前,SP再將資源返給瀏覽器,通常就是重定向到首頁瀑构;這里稍微提一下裆针,這次重定向一般會有如下幾種方案:
HTTP Redirect:通常你會失敗的。SAML Token太過巨大寺晌,URL長度有限世吨,Chrome或許還能做到,IE就算了呻征。
返回SP自定義token耘婚,將SAML放入session
再請求:就是在返回首頁后再通過JS向后端發(fā)送一個POST請求獲取SAML token,再將它存入localStorage
之后瀏覽器每次請求都會帶上token陆赋,一般就放在headers.authorization里沐祷;直到token過期,再循環(huán)上述步驟即可攒岛。
SAML缺陷
SAML是很成熟的單點登錄方案赖临,但是成熟有時候也可以說成陳舊。
NodeJS
我這里不是說Node不能用SAML灾锯;而是說兢榨,主流的saml庫太老了,多年不再維護顺饮,語法還處在callback回調(diào)地獄那個年代吵聪。我們剛開始還被callback惡心了許久,后來是自己封裝promisify才兼容目前的async-awit
語法的兼雄。
SPA
現(xiàn)代很多web app都是前端渲染的SPA應(yīng)用吟逝,我們自己的項目就是一個Vuejs的SPA,但在google里幾乎找不到靠譜的vue+saml的解決方案赦肋。
SAML設(shè)計的年代還是以后端渲染為主澎办,各種后端重定向前端頁面嘲碱。但如今spa設(shè)計——也就是所謂的前端渲染,基本就是前后分離局蚀,主要由前端實現(xiàn)路由跳轉(zhuǎn)麦锯。SAML的后端HTTP Redirect會有跨域限制。
上面還提到過琅绅,SAML本身過于巨大扶欣,不可能以URL的形式傳遞到前端。一般都是實現(xiàn)一套session機制千扶,自行管理token過期時間料祠;session設(shè)計需要持久化,比簡單的cookie驗證要復(fù)雜得多澎羞。即便強行實現(xiàn)api附帶SAML token髓绽,每次請求還是無端增加了許許多多的負載。
手機APP
如果SAML還需要支持手機APP單點登錄妆绞,事情可能會更曲折顺呕。以ISO為例,SSO還需要增加幾個步驟括饶,一般的設(shè)計有這么幾種:
當手機應(yīng)用需要IDP認證時株茶,先跳到Safari,完成登陸后再通過HTTP POST形式將token返回至APP
APP內(nèi)嵌
Webview
图焰,通過Webview
登陸并獲取tokenAPP自身提供login界面启盛,但登陸認證的全過程實際上是由代理服務(wù)器完成的
無論如何,SAML2.0畢竟是2005年的產(chǎn)物技羔;十多年過去了僵闯,SAML已不再適用于當今的許多跨平臺場景了。
小結(jié)
雖然最后diss了一下SAML藤滥,但SAML依舊是比較經(jīng)典的系統(tǒng)設(shè)計課題棍厂,能體會一番還是挺有收獲的。當然超陆,大家更應(yīng)該將SAML和現(xiàn)在比較常見的Auth2.0牺弹,Open ID,JWT等等技術(shù)一齊比較时呀,這樣才能在合適的時機選擇合適的技術(shù)张漂。