Single Sign-on
SSO是老生常談的話題了,但部分同學對SSO可能掌握的也是雲里霧里,一知半解。本次手撕公司的SSO原理,試圖以一種簡單、流暢的形式為你提供有用的SSO原理。
按照本人一貫行文風格,我們先說什么是SSO,為什么要提出SSO?
SSO: 在多個系統中,只需要登錄一次,就可以訪問其他相互信任的應用系統,表現的實際場景:
-
企業部署多個website,形成產品套件或產品矩陣,而賬號集中統一管理
-
用戶一次登錄,即可暢通不同域名下web服務
今天我們主要講不同頂域下SSO的實現,引出CAS原理,CAS傳送門:
手繪原理
用戶首次訪問website1
① 用戶訪問website1,website1需要認證, 用戶當前沒有登錄
② website1給瀏覽器返回302重定向, 瀏覽器重定向到SSO服務頁:www.sso-website.com?service=https://www.website1.com
context.Response.Redirect(ssoURL, false); // 臨時跳轉,建議傳參false返回302標准重定向響應
用戶並沒有登錄SSO系統,所以SSO系統會返回登錄界面
③ 用戶在SSO登錄頁輸入賬戶/密碼
④ 登錄成功,SSO會在瀏覽器寫入Cookie for sso[官方叫CASTGC]並產生一個302重定向,瀏覽器將重定向到原website1地址,並攜帶與此次SSO認證成功的ticket(ST)
http://www.website1.com?ticket=XXXX-OOOO-XXXX-OOOO
⑤ website1收到以上重定向請求,解析QueryString中的ticket, 向SSO做一次ticket驗證;
⑥⑦ 驗證通過之后,會寫入本站的Cookie for website1, 同時會302重定向要求回到業務首頁:www.website1.com。
已認證用戶訪問website2
① 用戶訪問website2,用戶在website2域並沒有認證;跳轉回www.sso-website.com?service=https://www.website2.com
② SSO檢測到該用戶在SSO域下存在Cookie for sso, 認定該用戶已經登錄,故跳轉回www.website2.com?ticket=XXXX-OOOO-XXXX-OOOO, 如上也會攜帶認證ticket
③ 如上,website2收到 website2.com?ticket=XXXX-OOOO-XXXX-OOOO請求,在做一次SSO驗證; 驗證成功,寫入本站Cookie for website2
重難點解讀
① SSO認證成功,寫入的cookie for sso, 是登錄到其他系統的關鍵
② website1收到SSO發起的重定向請求,解析出ticket=XXXX-OOOO-XXXX-OOOO, 為什么還要做一次SSO驗證?
因為website1收到的帶ticket請求,有可能是偽造(復制別人的帶ticket地址 www.website1.com?ticket=XXXX-OOOO-XXXX-OOOO,實際沒有sso登錄), 所以在website1中需要去SSO驗證一次(sso會驗證這個ticket在sso站點是否已經是登錄用戶)。
③ 標准的CAS登錄流程有三次302瀏覽器重定向, 分別由原站點website1啟動2次和SSO啟動一次
理論上流程由服務端重定向也是可以的 ?? 看官若發現有漏洞,可在評論區回復。
20200201 更新,三次跳轉均不可使用服務端跳轉!!!
第一次website1重定向回 sso.com,第二次SSO重定向回 website1.com不能使用服務端重定向, 服務端重定向相當於A站點請求了B站點的資源,瀏覽器地址並不會改變, 這樣的操作導致此流程並不能產生獨立的 Cookie for sso, Cookie for website1, 故不能使用服務端跳轉, 應保持302 跳轉(這是HTTP協議的行為)。
對於第三次重定向,發生在最后一步:跳轉回首頁 website1.com,頁面其他資源需使用剛寫入的Cookie for website1,故此處也不可使用 服務端跳轉。
④ 退出SSO登錄, 要做兩件事情:
- 向SSO發起api請求,請求SSO刪除用戶在SSO域下的認證cookie for sso
- 移除本站的cookie for website1
⑤ 每個website,至少需要如下sso配置
"SsoOptions": { "BaseAddress": "https://sso-cas.sso.com", // 基地址 "LoginPath": "/login", // sso登錄地址 "LogoutPath": "/api/logout", // 退出sso登錄的api地址 "ValidateTGTPath": "/api/validate", // 驗證ticket的api地址 "UserInfoPath": "/api/v2/userinfo" // 從sso拿到登錄用戶信息的api地址 },
That' all,這是自己對SSO登錄的一些理解, 本圖文希望以流暢的思路記錄SSO流程, 各位看官不要吃快餐,知其然更知其所以然很關鍵。