javascript
基于OIDC(OpenID Connect)的SSO(纯JS客户端)
在上一篇基于OIDC的SSO的中涉及到了4個Web站點:
oidc-server.dev:利用oidc實現(xiàn)的統(tǒng)一認(rèn)證和授權(quán)中心,SSO站點。
oidc-client-hybrid.dev:oidc的一個客戶端,采用hybrid模式。
oidc-client-implicit.dev:odic的另一個客戶端,采用implicit模式。
oidc-client-js.dev:oidc的又一個客戶端,采用implicit模式,純靜態(tài)網(wǎng)站,只有js和html,無服務(wù)端代碼。
其中hybrid和implicit這兩個站點都是具有在服務(wù)端執(zhí)行代碼的能力的(1,登錄需要在服務(wù)端做跳轉(zhuǎn);2,登錄狀態(tài)寫入cookie;3,通過服務(wù)端的接口接收被動的退出通知)。而js這個客戶端則是一個純粹的靜態(tài)網(wǎng)站,那么它是如何處理登錄和退出的呢?
oidc-client-js.dev這個web站點對應(yīng)的代碼位于web.oidc.client.js這個文件夾中(https://github.com/linianhui/oidc.example/tree/master/src/web.oidc.client.js):
JS Client 登錄
我們知道在瀏覽器中的JS是可以直接進(jìn)行頁面跳轉(zhuǎn)的,oidc的js客戶端就是利用這個來直接構(gòu)造認(rèn)證請求的URL,然后進(jìn)行登錄跳轉(zhuǎn)的(我們這里使用的是oidc-client.js這個開源的js庫來處理oidc規(guī)范相關(guān)的一下操作的)。下圖是打開oidc-client-js.dev后的頁面:
JS Client 直接發(fā)起認(rèn)證請求
我們點擊下Login。
可以看到Client這邊在對oidc-server.dev這個站點發(fā)起了2個請求之后就直接構(gòu)造了一個認(rèn)證請求的URL,并交給瀏覽器去發(fā)起了請求。
/account/js:我自己擴(kuò)展的,后面介紹其用途,目前暫時忽略它。
/.well-known/openid-configuration:這個是之前介紹到的OIDC提供的Discovery服務(wù),Client需要從這個服務(wù)返回的JSON中獲取認(rèn)證請求的接口地址以及其他的信息。
認(rèn)證請求這里面包含的參數(shù)和上篇中的信息并沒有什么差別,這里就不介紹了。
OIDC-Server 通過URL的#把數(shù)據(jù)傳遞給JS Client
瀏覽器會重定向到登錄頁面,我們登錄一下,登錄成功后會跳轉(zhuǎn)上面所填寫的redriect_uri參數(shù)指定的URL,并使用URL的#部分?jǐn)y帶認(rèn)證后的信息:
http://oidc-client-js.dev/oidc/login-callback.html#id_token=eyJhbGciOiJSUzI1NiIsImtpZCI6ImI2MmE2YTVlZjNiNGJmOTlhNWU3M2FkZmI1OTQ3NjRjIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MTE3NTEyMjgsImV4cCI6MTUxMTc1MTUyOCwiaXNzIjoiaHR0cDovL29pZGMtc2VydmVyLmRldiIsImF1ZCI6ImpzLWNsaWVudCIsIm5vbmNlIjoiZGU5NGI1NGMzNDk1NGFjMjg0Y2I0NzlhY2M5ZGMxMjMiLCJpYXQiOjE1MTE3NTEyMjgsImF0X2hhc2giOiJ1QnJhckVLOHk4elhwR0pJOG1BaE1nIiwic2lkIjoiMWQ2ZWQwYWI0ZjdhNzI2MDUxMzBiYjBkYjNiOTdkY2MiLCJzdWIiOiIwMDAwMDEiLCJhdXRoX3RpbWUiOjE1MTE3NTEyMjgsImlkcCI6ImxvY2FsIiwiYW1yIjpbImV4dGVybmFsIl19.EUMT0R34OKDuE8AESEnRAASoRCP2NCAy7EEkMdM9vBwfz8BGnrCGXiDnKoUgbw3qK8ekoiwhSed6qE-Xh5QqnnwQTOc_D0nucbA3CVqKDhc9TFonEHoU60ETbX0i70bbOThZeoJdto9CkILbcewk2SLgfCQXZzsKERm6AS7m9LUN7cGjQJQm6Ht5DpIgjFu7s9V7qnUfu7hjvI51zPmYgJwLtvCXb9vAxXy17oBrVTmYunDLETRnfj9UXcsSROOW6Ac6sKSLOtFkY5ElZuIa5Za_1GJFDaoYyZwFT53WWBO9-LBdIHd8Cqx5fyw8tlpT3qmdwf0scSr256sVXykGQw&access_token=eyJhbGciOiJSUzI1NiIsImtpZCI6ImI2MmE2YTVlZjNiNGJmOTlhNWU3M2FkZmI1OTQ3NjRjIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MTE3NTEyMjgsImV4cCI6MTUxMTc1NDgyOCwiaXNzIjoiaHR0cDovL29pZGMtc2VydmVyLmRldiIsImF1ZCI6WyJodHRwOi8vb2lkYy1zZXJ2ZXIuZGV2L3Jlc291cmNlcyIsIm15LWFwaSJdLCJjbGllbnRfaWQiOiJqcy1jbGllbnQiLCJzdWIiOiIwMDAwMDEiLCJhdXRoX3RpbWUiOjE1MTE3NTEyMjgsImlkcCI6ImxvY2FsIiwic2NvcGUiOlsib3BlbmlkIiwicHJvZmlsZSIsIm15LWFwaSJdLCJhbXIiOlsiZXh0ZXJuYWwiXX0.BU65olTuhLSlyFHyRzSHKUaFw5v5qMg7qmutl3LCel0gtjD9ky9cyD3rUNNAkalVcHXg7znN_F2JB71ape9mSD_L66H8pTTwaiMTxbPz9_HMEz9w6GgmOrjMGP8unIpCOKom1DV4EiSQoDe8P30oh2mwmA5SLvZixlAln3_ycArTd7440SCUrUvnEa1CJyl-K-kkLvLyl3TRo6bDE-H47-AzHq1NtA22cwleVXNxUtOsMHk1Nsa2tOFW6B4t3fAvo_MWx2BFkJMBToy4ArepLXSaN5CQQxH8na1Havll3Ly3c9GOslNsm1krMvx9GYdFR6DgjoDvNbaVDkLdmO2T_w&token_type=Bearer&expires_in=3600&scope=openid%20profile%20my-api&state=96af404863044d49b6e14a5827862538&session_state=C33U-BpeYNeLhWhUuKLfup18cjKkKX54yCdL2fUOtV0.5ec877a6108fde6ad04e774a770d7ee1
這里相比上一篇中返回的信息多了一個access_token是因為我們的認(rèn)證請求的response_type設(shè)置為了“id_token token”,故而oidc-server.dev把id_token和access_token一并給到了客戶端。
JS Client 解析#中的數(shù)據(jù),保存自己的登錄狀態(tài)
解析#后面的數(shù)據(jù)也是通過oidc-client.js?這個開源的庫來實現(xiàn)的。解析后的數(shù)據(jù)呈現(xiàn)在頁面上是如下這個樣子。
其中登錄后用戶的信息保存在瀏覽器的SessionStorage中:
JS Client 主動登出
退出操作和其他類型的客戶端一致,也是先清理自己保存的Session Storage,然后通知oidc-server.dev進(jìn)行登出,這里就不詳細(xì)解釋了。
JS Client 被動登出
我們知道在SSO中,除了自身主動退出登錄之外,還有其他的Client退出的時候,這里的JS Client也要被動的登出。由于JS Client沒有服務(wù)端在服務(wù)端執(zhí)行代碼的能力,其登錄狀態(tài)也是保存在客戶端這邊的,那么它就沒辦法接收像其他的客戶端一樣接收到登出的通知了。這個時候就需要客戶端自己主動去oidc-server.dev檢查登錄狀態(tài)了。這一部分在OIDC中也有標(biāo)準(zhǔn)規(guī)范,體現(xiàn)在OIDC的Discovery服務(wù)中的check_session_iframe字段中。
這個地址checksession的地址是oidc-server.dev的地址,那么這個地址返回的html頁面中,就可以通過js來檢查去存儲在cookie中的session信息的是否發(fā)生變化。然后通過H5中新增的postMessage來把這種變化傳遞給js client這邊。js client再去檢查一下是否已經(jīng)登出了。如果已經(jīng)登出,則會清理自身的登錄狀態(tài)來完成被動的登出操作。
比如下圖。我再oidc-client-implicit.dev點擊登出的時候,會觸發(fā)oidc-server.dev清理自己的cookie,然后js-client中使用check_session_iframe這個隱藏的iframe可以檢測到這種變化,從而使得js-client可以得知用戶已經(jīng)再其他的client退出登錄。
自動登錄
前面提到JS Client會加載一個oidc-server.dev/account/js的JS腳本文件,這個是我自己擴(kuò)展出來的一個腳本。它會在這個純靜態(tài)的網(wǎng)站在一開使打開的時候告訴客戶端oidc-server.dev是否已經(jīng)登錄了。
然后靜態(tài)的網(wǎng)站就可以利用account這個變量來決定是否再打開網(wǎng)站的時候就自動去登錄(由于其他站點已經(jīng)登陸過了,那么oidc-server.dev站點會自動攜帶登錄后的信息的再次跳轉(zhuǎn)回來)。
讀者可以打開瀏覽器,先打開oidc-client-implicit.dev這個站點并且登錄,然后再打開oidc-client-js.dev這個站點的時候,就會發(fā)現(xiàn)它會自動的登錄成功了。
總結(jié)
?本篇介紹了再瀏覽器中運行的純靜態(tài)的HTML網(wǎng)站使如何使用OIDC服務(wù)進(jìn)行單點登錄,統(tǒng)一登出,登錄狀態(tài)監(jiān)控,以及附加的如何讓JS Client自動登錄的原理。這里所使用的例子使傳統(tǒng)的HTML+JS的結(jié)構(gòu)。如果你使采用的Vue,Angular或者React的這類前端框架的話,那么其本質(zhì)上的原理也是完全一樣的,因為不管使采用的什么框架,最終輸出給瀏覽器的還是HTML+JS而已。
參考
本文源代碼:https://github.com/linianhui/oidc.example
oidc-client.js:https://github.com/IdentityModel/oidc-client-js
相關(guān)文章:
-
基于OIDC(OpenID Connect)的SSO
-
學(xué)習(xí)Identity Server 4的預(yù)備知識
-
使用Identity Server 4建立Authorization Server (1)
-
使用Identity Server 4建立Authorization Server (2)
-
使用Identity Server 4建立Authorization Server (3)
-
使用Identity Server 4建立Authorization Server (4)
-
使用Identity Server 4建立Authorization Server (5)
-
使用Identity Server 4建立Authorization Server (6) - js(angular5) 客戶端
-
IdentityServer4(10)- 添加對外部認(rèn)證的支持之QQ登錄
原文:http://www.cnblogs.com/linianhui/p/oidc-in-action-sso-with-js-client.html
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com
總結(jié)
以上是生活随笔為你收集整理的基于OIDC(OpenID Connect)的SSO(纯JS客户端)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 听云支持.NET Core的应用性能监控
- 下一篇: IIS中的 Asp.Net Core 和