天天看點

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

前一篇 Identity Server 4 - Hybrid Flow - MVC用戶端身份驗證:  https://www.cnblogs.com/cgzl/p/9253667.html

Claims

我不知道怎麼樣翻譯這個詞比較好, 是以我一般就不翻譯了.

在前一篇文章裡, MVC用戶端配置身份認證的時候有這麼一句話(Startup的ConfigureServices):

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

官方文檔是這樣介紹的: “我們關閉了JWT的Claim 類型映射, 以便允許well-known claims.”

如果我把這句話删掉, 然後再看看User.Claims的類型和值:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

現在有些claim的類型與ID Token裡面的類型名稱是不一樣, 也有一些claim不見了:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

而加上這句話之後, 現在User claim類型的名字就和ID Token裡面一樣了:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

再看一下ID Token:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

有一些claims并沒有出現在User.Claims裡面. 這是因為這個中間件預設情況下會過濾掉一些它認為我們不需要的claim, 例如nbf, amr等.

就先看下面這兩種情況吧:

1. 避免claims被預設過濾掉

如果我想讓中間件不要過濾掉nbf和, 也就是把nbf和amr從被過濾掉集合裡移除, 就可以使用這個方法:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

然後再看About頁面列印的UserClaims:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

這樣nbf和amr就不會被過濾掉了(從過濾掉的集合移除了).

2. 删除某些Claims

假如說我這個MVC用戶端不需要sid和idp, 那麼我可以使用下面的方法:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

這是一個擴充方法, 一定要注意它和Remove方法的差別.........

再次操作後, 可以看到這些Claims不見了:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

ClaimActions還有其他幾個方法, 請自行探索.

使用者資訊端點 UserInfo Endpoint 

盡管ID Token裡面可以包含很多使用者的claims, 但是盡量讓ID Token小一點比較好. 是以當MVC用戶端需要更多使用者資訊的時候可以手動請求使用者資訊端點, 這樣做也可以獲得使用者最新的其他資訊.

UserInfo Endpoint的官方文檔在這: 

http://openid.net/specs/openid-connect-core-1_0.html#UserInfo

它要求使用GET或者POST進行請求, 但建議使用GET. 此外請求還需要使用Access Token.

這是一個例子:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

成功請求的響應結果是一個JSON對象.

首先在IDP裡面再添加一個email scope:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

然後在配置的Client裡面添加這個scope:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

最後為TestUser添加email的claim:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

回到MVC用戶端的Startup, 這裡也需要添加email這個scope,

而且還要保證這個email不會出現在claims Identity裡面, 這樣我在請求使用者資訊端點的時候才會得到email而不是從User.Claims裡面得到:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

再次操作後, 可以看到User.Claims裡沒有出現email:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

下面我需要手動發送請求到使用者資訊端點來擷取其他資訊:

identity sever 4的這部分文檔在: 

https://identityserver4.readthedocs.io/en/release/endpoints/userinfo.html#identitymodel

https://github.com/IdentityModel/IdentityModel2

文檔提到, 需要為MVC用戶端安裝IdentityModel這個庫:

dotnet add package IdentityModel      

随後, 我把擷取使用者email的代碼還是放在About Action裡:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

首先通過IDP的URI獲得discovery document, 然後從中取出UserInfo端點, 從Cookie裡得到access token, 并用access token從使用者資訊端點獲得claims, 從這些claims裡面取得email并傳遞到About.cshtml.

相應的修改一下About.html:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

重新操作後看About頁面:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

對MVC用戶端使用基于角色對授權

首先需要在IDP那裡對兩個使用者添加role這個claim:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

分别是管理者角色和注冊使用者角色.

OpenID Connect并沒有定義關于角色role相關的scope, 是以我還需要自定義一個scope:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

第一個參數是scope的名字, 第二個參數是scope的顯示名, 第三個參數是它所包含的claim類型, 這裡就是“role”.

然後還需要用戶端允許請求“roles”這個scope:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

IDP這邊配置完了, 下面是MVC用戶端的配置, 打開MVC的startup, 添加“roles”這個scope:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

下面測試, 可以看到在同意頁面确實請求了角色“roles”這個scope:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

然後同意後卻無法從User.Claims裡看到角色role 這個claim:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

這是因為ASP.NET預設對UserInfo傳回的JSON資料裡一些常用的頂層claim進行了映射, 以便它們能夠出現在User.Claims裡面.

我也隻需要把JSON裡面的role claim, 映射到User.Claims裡即可:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

再次操作後, 就可以在User.Claims看到角色了:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

然後我便可以在MVC用戶端的任意地方通過角色來控制使用者的通路權限了, 例如:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

但是如何把role claim映射成ASP.NET Core MVC可以識别的角色Roles呢?

可以在MVC裡這樣配置:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

該參數主要是配置驗證Token的一些東西, 然而它還可以指定用戶端的Name 和 Role Claim的類型.

操作後用兩個使用者分别測試一下, Nick 管理者, 可以通路About:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

另一個使用者, Dave 注冊使用者, 則不可以通路About:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

這說明角色已經被MVC用戶端識别了.

但是對于Dave這個使用者來說, 沒有權限通路About時, 頁面顯示非常不友好, 是以下面解決這個問題.

首先建立一個AuthroizationController:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

然後建立相關的view:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

最後在Startup裡面配置, 如果沒有權限就跳轉到這個Action上:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

再次操作後, Dave點選About後就會因為權限不足而跳轉到該頁面:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權

今天先到這, 我自己幾乎不用MVC, 我主要是做Web API的, 這部分的内容大部分來自官方文檔和其他一些資料綜合出來的.

代碼: 

https://github.com/solenovex/Identity-Server-4-Tutorial-Code

 02部分

下面是我的關于ASP.NET Core Web API相關技術的公衆号--草根專欄:

Identity Server 4 - Hybrid Flow - ClaimsClaims對MVC用戶端使用基于角色對授權