基於IdentityServer4的OIDC實現單點登陸(SSO)原理簡析

Image result for SSO

# 寫在前面html

IdentityServer4的學習斷斷續續,兜兜轉轉,走了很多彎路,也花了很多時間。多是由於沒有閱讀源碼,也沒有特別系統的學習資料,相關文章不少園子裏的大佬都有涉及,有系列文章,好比:git

曉晨大佬的:http://www.javashuo.com/article/p-dqjlhqbm-hw.htmlgithub

蟋蟀 大佬的:
https://www.cnblogs.com/xishuai/tag/[34]%E5%B0%8F%E8%8F%9C%E5%AD%A6%E4%B9%A0%E7%BC%96%E7%A8%8B-IdentityServer4/web

李念輝楊旭大佬均有相關文章,翻翻即可找到,就不一一列舉了。apache

可是,不知你們有沒有體會,好像看了不少id4(IdentityServer4,下同)的文章,對:跨域

  • oidc到底是個什麼蛤蟆?
  • OAuth2.0和OpenId Connect究竟有啥區別?
  • id4切確是什麼東西?
  • id4能幹些啥?
  • id4爲何這麼設計?
  • id4各受權流程的區別是啥?
  • id4的SSO是基於什麼原理?

我仍是時不時:安全

1563344414401

老實說,這些問題我也一懂半懂,還有就是看多了、時間跨度大,有的覺得懂了提筆又忘了。這時大佬確定說:服務器

」誰叫你不去看源碼?「cookie

我默默的留下了兩行老淚:立刻看,立刻看。session

可是我以爲id4不少新手和我同樣都有這困擾,上手門檻確實有的高。誠然看源碼是個不錯的學習方法,但上來就讓新人或使用者看源碼,無疑很不利於推廣、直接勸退啊,畢竟大部分都是跟我同樣的菜逼(對不起拖後腿了)。

對應前面提到的一串問題,我不打算在本文一一解答,我今天着重想聊的是:

id4的SSO是基於什麼原理?

寫本文的初衷是看到李念輝大佬的https://www.cnblogs.com/linianhui/p/oidc-in-action-sso.html,因此本文算算是讀博筆記。

啥是SSO?

SSO,全稱Single sign-on :在多個應用系統中,只須要登陸一次,就能夠訪問其餘相互信任的應用系統。

好比你登陸京東後查看個人訂單:https://order.jd.com 而後再去查看購物車https://cart.jd.com/cart.action就不須要從新登陸。雖然這裏頂級域名一致,但其實單點登陸並無此要求。

單點登陸,很容易望文生義,覺得單點登陸就是限制用戶只能在一處登陸。

下面咱們說說咱們咱們經常使用的SSO的經常使用的實現方式。

SSO--基於Cookie的實現簡析

這種方式比較簡單,使用也比較普遍。

好比我有兩個系統:a.example.com 和 b.example.com,很簡單,只須要搞個 passport.example.com 登陸成功後往:example.com 這個頂級域寫登陸成功的cookie就好了。然後無論你是c.example.com仍是d.example.com或是+∞.example.com都只須要驗證登陸的cookie就行,簡單方便。

不過這種實現方式有個比較大的缺陷:

不能跨域,不能跨頂級的域。

我不能說我登陸成功後往jd.com域名下寫cookie吧。還有就是每一個業務域名都要作登陸cookie的校驗邏輯 ,不過這算小問題。

既然存在問題,就解決問題吧(這實在沒辦法解決發現問題的人啊)

SSO--基於CAS流程實現簡析

CAS簡介

Central Authentication Service,簡稱:CAS, 是一個單點登陸框架或者說解決方案,開始是由耶魯大學的一個組織開發,後來歸到apereo管理。 同時CAS也是開源的,遵循apache 2.0協議,目前代碼放在github上:https://github.com/apereo/cas

打開就驚呆了,看到吧,一堆開源項目在用,這logo閃瞎個人鈦合金狗眼了

img

咱們看下github簡介:

」CAS是一個企業級的、與語言無光的Web SSO解決方案,同時也嘗試整合受權和鑑權的需求。「

既然它是一個解決方案,那咱們看看它到底提出了啥。

CAS的方案泳道圖分析

CAS SSO標準流程,看圖說話吧。

右鍵可看查原圖

1563350641022

咱們看看發生了啥:

站點App1

  1. 用戶首次訪問web App1,App1發現用戶未登陸,攜帶目前訪問地址302到CAS Server登陸頁。
  2. CAS Server登陸頁檢查登陸Session不存在,返回一個登陸頁面。
  3. 填寫帳號,點擊登陸。
  4. CAS Server驗證帳號信息成功,建立一個Ticket Granting Ticket(TGT),這個TGT就是當前登陸用戶的session key。同時,建立一個service ticket並攜帶service ticket key,st key 做爲參數跳轉回App1。
  5. App1用get發送st key 去CAS Server驗證,驗證經過後返回登陸用戶信息。
  6. App1使用返回的登陸用戶信息構建當前系統的登陸狀態,並用一個JSESSIONID標記(JSESSIONID是Apache的默認名),並攜帶這個JSESSIONID從新訪問App1。
  7. App1驗證JSESSIONID,登陸成功,展現登陸成功頁面。
  8. 第二次訪問,驗證JSESSIONID,直接訪問。

站點App2

  1. 用戶首次訪問web App2,App2發現用戶未登陸,攜帶目前訪問地址302到CAS Server登陸頁。
  2. CAS Server登陸頁攜帶有App1生成的TGT,那麼直接作TCT的驗證,驗證成功不須要登陸,建立一個App2的st key,302回App2。
  3. 後續和以上的5,6,7,8 補邏輯相同,不贅述。

CAS的流程大概於此,實際的實現可能會複雜一點,可能會遇到各式各樣的問題。但有理論支撐,整體實現起來仍是簡單,可靠有保證的。

下面說說基於Id4的OIDC是怎麼作單點登陸的。

SSO--基於Id4的OIDC實現簡析

先準備環境

把官方samples下下來:https://github.com/IdentityServer/IdentityServer4/tree/master/samples

我刪掉了其餘項目,剩下這兩個,一目瞭然:

1563357538537

分別把這兩個站點部署爲:

http://odic.server.net

http://sso.client.net

咱們再看一眼Idoc服務端配置:

1563359425969

配置IdentityServer,Configs添加這麼一個客戶端:

// sso implicit client
new Client
{
    ClientId = "ssoimplicit",  //這個client id 跟 MfcImplicit 裏面的配置要一致
    ClientName = "sso implicit clinet",
    AllowedGrantTypes = GrantTypes.Implicit,                
    RedirectUris = { "http://sso.client.net/signin-oidc" },
    PostLogoutRedirectUris = { "http://sso.client.net/signout-callback-oidc" },
    AllowedScopes = new List<string>
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        IdentityServerConstants.StandardScopes.Email
    }
}

ok,咱們用下抓包工具觀察下登陸流程。

一、受保護客戶端頁面的訪問

sso.client.net是客戶端,而登陸頁在sso.client.net服務端

咱們先打開須要登陸才能夠訪問的:http://sso.client.net/Home/Secure

1563360012928

這裏302到了受權端點 http://odic.server.net/connect/authorize

二、受權端點對客戶端請求的驗證

這就是步驟1中, 302挑戰的受權端點攜帶的參數。

1563360754036

咱們先看看這些參數

client_id:ssoimplicit //咱們前面配置的clinenid=
reponse_mode:form_post //指示oidc服務器返回數據的形式是form表單
response_type:id_token //區別於oauth2受權請求的一點,必須包含有id_token這一項。
scope:openid profile //區別於oauth2受權請求的一點,必須包含有openid這一項。
state:oauth2定義的一個狀態字符串,這裏的實現是加密保存了一些客戶端的信息,讓你最後能夠在登陸成功後帶回到客戶端,這個參數聽重要的
nonce:上一步中寫入cookie的值,這字符串未來會包含在idtoken中原樣返回給客戶端,作安全校驗用。
redirect_uri:http://sso.client.net/signin-oidc //認證成功後的回調地址,就是咱們配置裏面的

受權端點有不少功能,這裏主要作了兩件事:

  1. 先判斷待過來的參數是否合法,好比clientid是否是配置裏面的,參數有沒有按要求、規範傳過來,參數是否被篡改,未驗證經過會報錯。
  2. 受權與否的校驗,根據攜帶的參數,判斷若是登陸,就直接回調 redirect_uri參數地址:http://sso.client.net/signin-oidc,否,302到登陸頁,引導用戶登陸

三、登陸

初次登陸,步驟2中的受權端點判斷當前未登陸,仍是302,跳轉登陸頁,引導用戶登陸受權。

1563377800657

點擊登陸,跳轉到是否受權頁面,這個頁面不必定展現,可經過配置Client的RequireConsent=false,跳過這個頁面。

1563377823909

of course Yes!

四、登陸成功,客戶端構建登陸狀態

咱們看看點Yes Alow 以後的請求。

1563377932877

能夠清楚的看到去到了:

http://odic.server.net/connect/authorize/callback

callback,哦,這是一個登陸回調,它幹了啥呢,咱們仔細看響應:

1563377968466

哦,它這裏響應回了一個頁面,這個頁面只有一個表單,當頁面一加載完成馬上post表單到:action='http://sso.client.net/signin-oidc' 這個地址。而且仔細看看錶單的參數,前面的那些scope、state啊這些參數全都帶了過來,有意思,沒錯,這精妙的設計也是規範之一。

這裏它爲何不帶上clientid呢?哈哈,客戶端本身確定知道本身的clientid的,另外,還有中間這一大串的id_token你忘了嗎,這裏面但是能夠攜帶信息的哦。

來,咱們看看這個id_token到底是何方妖孽。

1563378011291

咱們看到id_token帶有登陸用戶的信息:

iss:token發放的服務器地址

aud:clientid

sid:會話信息

kid:當前token的標識符

name:用戶名

此外還有好比id_token的發放時間,過時時間,nonce,用戶非機密信息等等。還有藍色部分須要使用客戶端公鑰驗證的簽名等等。

這個時候客戶端已經拿到登陸用戶的信息了,這時客戶端直接使用登陸用戶信息,構建當前應用sso.client.net的登陸狀態便可。

好比下面的這個 Set名爲Implicit的Cookie:

1563378070054

這個Cookie是能夠刪掉的,它自己只維持了在sso.client.net的登陸狀態而已,若是你刪掉它,它就會從新跑到受權端點:http://odic.server.net/connect/authorize 去驗證一下,發現當前會話仍是處於登陸狀態的,而後又302到登陸回調地址http://sso.client.net/signin-oidc,而後/signin-oidc從state參數裏面取出redirect_url,302回到當前頁面。

最後咱們來看一下登陸成功的頁面

1563378088904

單點登出

單點登出我就不細說了,使用:

//指定登陸方案的方式登出
await HttpContext.SignOutAsync(IdentityServerConstants.DefaultCookieAuthenticationScheme);

//或者直接
await HttpContext.SignOutAsync();

暴力點刪除cookie也能夠,不過那隻能算是半退出狀態吧。

總結

經過對以上一個使用Id4構建的OIDC實現的登陸流程來看,OIDC的SSO它徹底無光域名的,id4登陸成功後,客戶端經過使用id_token來構建自身的登陸狀態,一個client如此,N個皆然。

你們好像感受這個SSO的實現方式跟前面的CAS流程很像誒,咱們再看一遍前面CAS的圖

1563378173769

好像是發現了啥不得了的東西。

沒錯:openid也是基於CAS流程的一個實現(我根據理解猜的 沒有證據)。

再多說兩句

id4確實是好東西,暫時用不上也要多瞭解、學習,最好寫個博客作個筆記加深下理解。

在理解的基礎上不要去背各類Flow有啥區別什麼的,知道什麼場景下用那種流程就行,也沒幾個。

善用官方文檔、Sample。

本文示例源碼

https://github.com/gebiWangshushu/cnblogs-demos

參考

https://yq.aliyun.com/articles/636281

https://www.cnblogs.com/linianhui/p/oidc-in-action-sso.html

相關文章
相關標籤/搜索