日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

基于OIDC(OpenID Connect)的SSO

發(fā)布時間:2023/12/4 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于OIDC(OpenID Connect)的SSO 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在[認證授權]系列博客中,分別對OAuth2和OIDC在理論概念方面進行了解釋說明,其間雖然我有寫過一個完整的示例(https://github.com/linianhui/oidc.example),但是卻沒有在實踐方面做出過解釋。在這里新開一個系列博客,來解釋其各種不同的應用場景。因為OIDC是在OAuth2之上的協(xié)議,所以這其中也會包含OAuth2的一些內(nèi)容。

OIDC協(xié)議本身有很多的開源實現(xiàn),這里選取的是基于.Net的開源實現(xiàn)基于IdentityServer4。本系列的源代碼位于https://github.com/linianhui/oidc.example。clone下來后用管理員身份運行build.ps1來部署整個系統(tǒng),其中可能會彈出UAC警告(腳本會修改host文件,記得允許管理員讀寫這個文件先)。部署完后的樣子如下:

本文中主要是關注一下SSO這部分的內(nèi)容,主要是跨一級域單點登錄統(tǒng)一登出功能。其中涉及到的站點有一下4個:

  • oidc-server.dev:利用oidc實現(xiàn)的統(tǒng)一認證和授權中心,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,無服務端代碼。

  • 單點登錄

    通常來講,SSO包括統(tǒng)一的登錄統(tǒng)一的登出這兩部分?;贠IDC實現(xiàn)的SSO主要是利用OIDC服務作為用戶認證中心作為統(tǒng)一入口,使得所有的需要登錄的地方都交給OIDC服務來做。更直白點說就是把需要進行用戶認證的客戶端中的用戶認證這部分都剝離出來交給OIDC認證中心來做。具體的交互流程如下:

    其中這三個客戶端是完全獨立的位于不同的域名之下,且沒有任何依賴關系,三者均依賴oidc-server.dev這個站點進行認證和授權,通信協(xié)議為HTTP,那么下面則通過它們之間的HTTP消息來解釋其具體的流程。這個過程中使用fiddler來進行監(jiān)視其所有的請求。

    第1步:OIDC-Client- 觸發(fā)認證請求

    在瀏覽器打開oidc-client-implicit.dev這個站點,打開后如下(QQ這個先不管它,后面單獨介紹)。

    點擊Oidc Login后,會觸發(fā)一個302的重定向操作。具體的HTTP請求和響應信息如下:

    Request:Get后面的URL是我們點擊Oidc Login的Url,這個URL包含一個參數(shù),代表登錄成功后所要回到的頁面是哪里。

    Response:服務器返回了一個302重定向。

  • Location的Url指向了oidc-server.dev這個站點,其中還攜帶了一大堆參數(shù)(參數(shù)后面一小節(jié)介紹);

  • Set-Cookie設置了一個nonce的cookie,主要目的用于安全方面。

  • 第2步:OIDC-Client - 認證請求

    緊接上一步,瀏覽器在接收到第1步的302響應后,會對Location所指定的URL發(fā)起一個Get請求。這個請求攜帶的參數(shù)如下:

    其中參數(shù)的含義在OIDC的認證請求有詳細的解釋(注:其中采用的認證類型不管是authorization code,或者implict,還是hybrid都無關緊要,它們的區(qū)別只是其適用場景的差異,并不影響整個流程)。

  • client_id=implicit-client:發(fā)起認證請求的客戶端的唯一標識,這個客戶端事先已經(jīng)在oidc-server.dev這個站點注冊過了。

  • reponse_mode=form_post:指示oidc服務器應該使用form表單的形式返回數(shù)據(jù)給客戶端。

  • response_type=id_token:區(qū)別于oauth2授權請求的一點,必須包含有id_token這一項。

  • scope=openid profile:區(qū)別于oauth2授權請求的一點,必須包含有openid這一項。

  • state:oauth2定義的一個狀態(tài)字符串,這里的實現(xiàn)是加密保存了一些客戶端的狀態(tài)信息(用于記錄客戶端的一些狀態(tài),在登錄成功后會有用處),oidc會在認證完成后原樣返回這個參數(shù)。

  • nonce:上一步中寫入cookie的值,這字符串將來會包含在idtoken中原樣返回給客戶端。

  • redirect_uri:認證成功后的回調(diào)地址,oidc-server.dev會把認證的信息發(fā)送給這個地址。

  • 第3步:OIDC-Server - 驗證請求信息

    oidc-server.dev站點會驗證第2步中傳遞過來的信息,比如client_id是否有效,redircet_uri是否合法,其他的參數(shù)是否合法之類的驗證。如果驗證通過,則會進行下一步操作。

    第4步:OIDC-Server - 打開登錄頁面

    在oidc-server.dev站點驗證完成后,如果沒有從來沒有客戶端通過oidc-server.dev登陸過,那么第2步的請求會返回一個302重定向重定向到登錄頁面。如果是已經(jīng)登錄,則會直接返回第5步中生產(chǎn)重定向地址

    瀏覽器會打開響應消息中Location指定的地址(登錄頁面)。如下:

    第5步:OIDC-Server - 完成用戶登錄,同時記錄登錄狀態(tài)

    在第四步輸入賬戶密碼點擊提交后,會POST如下信息到服務器端。

    服務器驗證用戶的賬號密碼,通過后會使用Set-cookie維持自身的登錄狀態(tài)。然后使用302重定向到下一個頁面。

    第6步:瀏覽器 - 打開上一步重定向的地址,同時自動發(fā)起一個post請求

    form的地址是在第2步中設置的回調(diào)地址,form表單中包含(根據(jù)具體的認證方式authorization code,implict或者hybrid,其包含的信息會有一些差異,這個例子中是采用的implicit方式)如下信息:

  • id_token:id_token即為認證的信息,OIDC的核心部分,采用JWT格式包裝的一個字符串。

  • scope:用戶允許訪問的scope信息。

  • state:第1步中發(fā)送的state,原樣返回。

  • session_state:會話狀態(tài)。

  • id_token包含的具體的信息如下:

    其中包含認證的服務器信息iss,客戶端的信息aud,時效信息nbf和exp,用戶信息sub和nickname,會話信息sid,以及第1步中設置的nonce。還有其簽名的信息alg=RS256,表示idtoken最后的一段信息(上圖中淺藍色的部分)是oidc-server.dev使用RSA256對id_token的header和payload部分所生產(chǎn)的數(shù)字簽名。客戶端需要使用oidc-server.dev提供的公鑰來驗證這個數(shù)字簽名。

    第7步:OIDC-Client - 接收第6步POST過來的參數(shù),構建自身的登錄狀態(tài)

    客戶端驗證id_token的有效性,其中驗證所需的公鑰來自OIDC的發(fā)現(xiàn)服務中的jwk_uri,這個驗證是必須的,目的時為了保證客戶端得到的id_token是oidc-sercer.dev頒發(fā)的,并且沒有被篡改過,以及id_token的有效時間驗證。數(shù)字簽名的JWT可以保證id_token的不可否認性,認證和完整性,但是并不能保證其機密性,所以id_token中千萬不要包含有機密性要求的敏感的數(shù)據(jù)。如果確實需要包含,則需要對其進行加密處理(比如JWE規(guī)范)。其中驗證也包含對nonce(包含在id_token中)的驗證(第1步設置的名為nonce的cookie)。

    在驗證完成后,客戶端就可以取出來其中包含的用戶信息來構建自身的登錄狀態(tài),比如上如中Set-Cookie=lnh.oidc這個cookie。然后清除第1步中設置的名為nonce的cookie。

    最后跳轉(zhuǎn)到客戶端指定的地址(這個地址信息被保存在第1步中傳遞給oidc-server.dev的state參數(shù)中,被oidc-server.dev原樣返回了這個信息)。然后讀取用戶信息如下(這里讀取的是id_token中的完整信息):

    其他的客戶端登錄

    登錄流程是和上面的步驟是一樣的,一樣會發(fā)起認證請求,區(qū)別在于已經(jīng)登錄的時候會在第4步直接返回post信息給客戶端的地址,而不是打開一個登錄頁面,這里就不再詳細介紹了。大家可以在本地運行一下,通過fiddler觀察一下它們的請求流程。貼一下oidc-client-hybrid.dev這個客戶端登錄后的頁面吧:

    統(tǒng)一退出

    退出的流程相比登錄簡單一些。如下圖:

    其中核心部分在于利用瀏覽器作為中間的媒介,來逐一的通知已經(jīng)登錄的客戶端退出登錄。

    第1步:OIDC-Client - 觸發(fā)登出請求

    點擊Logout鏈接。

    點擊退出后會觸發(fā)一個GET請求,如下:

    上圖這個請求會返回一個302的響應,Location的地址指向oidc-server.dev的一個endsession的接口。同時會通過Set-Cookie來清除自身的cookie。

    第2步:OIDC-Client - 登出請求

    瀏覽器通過GET訪問上一步中指定的Location地址。

    接口地址定義在OIDC的發(fā)現(xiàn)服務中的end_session_endpoint字段中,參數(shù)信息定義在OIDC的Front-Channel-Logout規(guī)范中。

    第3步:OIDC-Server - 驗證登出請求

    驗證上圖中傳遞的信息,如果信息無誤則再一次重定向到一個地址(這里是IdentityServer4的實現(xiàn)機制,其實可以無需這個再次重定向的)。

    第4步:OIDC-Server - 登出自身,返回包含IFrame的HTML

    瀏覽器打開第3步中重定向的地址:

    響應中會通過Set-Cookie(idsrv和idsrv.session)清除oidc-server.dev自身的登錄狀態(tài)。然后包含一個HTML表單頁面,上圖中iframe指向的地址是IdentityServer4內(nèi)部維持的一個地址。訪問這個地址后的信息如下:

    1 <!DOCTYPE html>2 <html>3 <style>iframe{display:none;width:0;height:0;}</style>4 <body>5 <iframe src='http://oidc-client-implicit.dev/oidc/front-channel-logout-callback?sid=b51ea235574807beb0deff7c6db6a381&iss=http%3A%2F%2Foidc-server.dev'></iframe>6 <iframe src='http://oidc-client-hybrid.dev/oidc/front-channel-logout-callback?sid=b51ea235574807beb0deff7c6db6a381&iss=http%3A%2F%2Foidc-server.dev'></iframe>7 </body>8 </html>

    上面代碼中的iframe是真正的調(diào)用已經(jīng)登錄的客戶端進行登出的地址(IdentityServer4會記錄下來已經(jīng)登錄的客戶端,沒有登陸過的和沒有配置啟用Front-Channel-Logout的則不會出現(xiàn)在這里)。其中iframe指向的地址是OIDC客戶端在oidc-server.dev中注冊的時候配置的地址。參數(shù)則是動態(tài)附加上去的參數(shù)。

    最后頁面中包含一個js腳本文件,在頁面load完成后,跳轉(zhuǎn)到第2步中指定的post_logout_redirect_uri指向的回調(diào)頁面。

    第5步:OIDC-Client - 處理登出回調(diào)通知

    在瀏覽器訪問上面代碼中iframe指向的地址的時候,被動登出的OIDC客戶端會接收到登出通知。

    響應中通過Set-Cookie(lnh.oidc)清除了需要被動登出的客戶端的Cookie。至此,統(tǒng)一的登出完成。

    總結

    本文介紹了基于OIDC實現(xiàn)的SSO的工作原理和流程,但并未涉及到OIDC的具體實現(xiàn)IdentityServer4的是如何使用的(這部分通過讀我提供的源碼應該是很容易理解的),旨在解釋一下如何用OIDC實現(xiàn)SSO,而非如何使用OIDC的某一個實現(xiàn)框架。OIDC是一個協(xié)議族,這些具體每一步怎么做都是有標準的規(guī)范的,所以側(cè)重在了用HTTP來描述這個過程,這樣這個流程也就可以用在java,php,nodejs等等開發(fā)平臺上。

    參考

    本文源代碼:https://github.com/linianhui/oidc.example

    認證授權:http://www.cnblogs.com/linianhui/category/929878.html

    Id Token:http://www.cnblogs.com/linianhui/p/openid-connect-core.html#auto_id_5

    JWT:http://www.cnblogs.com/linianhui/p/oauth2-extensions-protocol-and-json-web-token.html#auto_id_5

    數(shù)字簽名:http://www.cnblogs.com/linianhui/p/security-based-toolbox.html#auto_id_16

    OIDC:http://openid.net/connect/

    IdentityServer4:https://github.com/IdentityServer/IdentityServer4


    原文:http://www.cnblogs.com/linianhui/p/oidc-in-action-sso.html


    .NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com

    總結

    以上是生活随笔為你收集整理的基于OIDC(OpenID Connect)的SSO的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。