這個系列文章介紹的是Identity Server 4 的 Hybrid Flow, 前兩篇文章介紹瞭如何保護MVC客戶端, 本文介紹如何保護API資源. 保護MVC客戶端的文章: https://www.cnblogs.com/cgzl/p/9253667.html, https://www.cn ...
這個系列文章介紹的是Identity Server 4 的 Hybrid Flow, 前兩篇文章介紹瞭如何保護MVC客戶端, 本文介紹如何保護API資源.
保護MVC客戶端的文章: https://www.cnblogs.com/cgzl/p/9253667.html, https://www.cnblogs.com/cgzl/p/9268371.html
相關代碼: https://github.com/solenovex/Identity-Server-4-Tutorial-Code 裡面03那部分.
回顧 Hybrid Flow
回顧一下該項目使用的流程
圖裡有IDP (Identity Provider, 我例子里是用Identity Server 4構建的項目)和客戶端(我的例子里是MVC客戶端).
在上面流程走完之後, MVC客戶端獲得了Access Token, MVC客戶端驗證Access Token併成功後, 就可以使用Access Token來訪問被保護的API資源了, 而Access Token會在被保護的API那裡再次進行驗證.
保護API
首先在IDP里配置一個返回ApiResoruce的方法:
和IdentityResource類似, ApiResource就是與API相關的scopes.
在Client配置那裡, 把這個ApiResource的名字添加到允許的scopes里:
最後在IDP的startup里, 註冊ApiResources:
現在來到MVC客戶端這裡, 需要把上面的scope添加上:
最後來到API項目, 首先確保使用HTTPS:
API項目還需要安裝IdentityServer4.AccessTokenValidation這個包, 可以通過Nuget安裝.
安裝後, 還需要進行配置 (官方文檔: https://identityserver4.readthedocs.io/en/release/quickstarts/1_client_credentials.html#adding-an-api):
其中IdentityServerAuthenticationDefaults.AuthenticationScheme 就是 “Bearer” 的意思, 這裡使用的就是這個方案.
AddIdentityServerAuthentication()方法註冊了Access Token 驗證的處理者. 裡面Authority就是IDP的URI, ApiName就是IDP里配置的API的名字.
在Startup的Configure方法里, 還需要把它添加到管道:
要確保它在UseMVC之前調用.
我在API項目里使用過濾器為所有的Controller都加上了授權過濾:
當然也可以在具體的Controller或Action級寫上這個:
無論如何現在訪問Country資源是需要授權的.
回到MVC客戶端, 在Home的Contact Action里調用CountryAPI資源:
下麵測試一下未使用Access Token訪問被保護的Country資源的情況, 重新操作可以看到用戶同意授權頁面出現了剛纔配置的API資源名:
在訪問Contact頁面的時候, 提示未授權:
那就用之前介紹過的方法來獲取Access Token並設置Authorization Header為 “Bearer [AccessToken]” 即可:
再修改一下Contact頁面, 顯示Access Token:
重新操作, 就可以看到Country資源數據了:
Access Token
去jwt.io對Access Token進行解碼:
看一下aud (audience, 觀眾) 這個屬性, 它有兩個值, 第一個是指IDP那邊對資源 (調用用戶信息端點), 第二個就是指API那個項目.
這個屬性說明這個access token是為它們倆準備的.
而scope裡面的“restapi”就是aud裡面的“restapi”, 所以這個token允許被用來訪問我們的“restapi”.
而scope裡面的“profile”等scopes是對應另一個aud的值, 這些scopes來自IDP那裡.
現在Access Token有這些claims, API也就能得到這些claims, 但是有時API還需要用戶身份相關的claims.
修改IDP的ApiResource配置即可:
再次操作後, 查看token, 就可以看到我剛剛添加的那兩個claim了:
而role這個claim, 在API里是可以被識別成角色的, 如果我在API的Action上設置許可權如下:
那麼, Nick這個用戶就可以得到Country數據, 而Dave則會顯示403 Forbidden: