前言
在前幾篇的學習中,我們定義的 ApiResource、ApiScope、IdentityResource 都是存儲在內存中的,通過 AddInMemoryApiScopes(Startup.GetApiScopes())、AddInMemoryIdentityResources(Startup.GetIdentityResources())、 AddInMemoryApiResources(Startup.GetApiResources()) 的方式注入到 IDS4 的服務中。本篇我們學習如何使用數據庫或其他持久化方法存儲和讀取 Resource 。
IdentityServer4 中 Resource 概念
在 IdentityServer4 中一共有3種資源類型:IdentityResource、ApiResource、ApiScope,定義這些資源的名稱必須是唯一的,不可重復。
IdentityResource
身份資源,表示關於用戶的聲明,如用戶ID、顯示名、電子郵件地址等。
ApiResource
對 ApiScope 高層分組(歸類)。當 API 資源變大時,使用 ApiScope 作用域列表可能不可行。通常需要引入某種名稱空間來組織作用域名稱,可能還希望將它們分組在一起,並獲得一些更高級的構造,如訪問令牌中的受眾聲明。如:多個資源應該支持相同的作用域名稱,但是有時您顯式地希望將一個作用域隔離到某個資源。 在IdentityServer中,ApiResource類允許一些額外的組織
ApiScope
資源作用域。
IResourceStore 接口
IDS4 為開發者定義了一個 IResourceStore 接口,實現該接口即可做自己的 Resource 持久化存儲和讀取。
CustomerResourceStore 實現
新建 CustomerResourceStore 類,實現 IResourceStore 接口,寫我們自己的資源查找規則。
為了簡單,筆者使用的 Resource 全部是已賦值好的內容,筆友可以通過數據庫或其他持久化介質獲取 Resource。
FindIdentityResourcesByScopeNameAsync
/// <summary> /// 身份資源 /// </summary> private readonly List<IdentityResource> identityResources = new List<IdentityResource> { new IdentityResources.OpenId(), new IdentityResources.Profile() };
/// <summary> /// 通過 名稱 查找符合要求的 IdentityResources /// </summary> /// <param name="scopeNames"></param> /// <returns></returns> public async Task<IEnumerable<IdentityResource>> FindIdentityResourcesByScopeNameAsync(IEnumerable<string> scopeNames) { var result = new List<IdentityResource>(); foreach (var name in scopeNames) { if (identityResources.Count(t => t.Name == name) > 0) { result.Add(identityResources.First(t => t.Name == name)); } } return result; }
FindApiResourcesByNameAsync
/// <summary> /// ApiResource 資源 /// </summary> private readonly List<ApiResource> apiResources = new List<ApiResource> { new ApiResource("admin", "用戶管理"){ Scopes = { "user.list" , "user.delete" } }, new ApiResource("article", "文章管理"){ Scopes = { "article.list" , "article.delete" } }, };
/// <summary> /// 通過 名稱 查找符合要求的 ApiResources /// </summary> /// <param name="apiResourceNames"></param> /// <returns></returns> public async Task<IEnumerable<ApiResource>> FindApiResourcesByNameAsync(IEnumerable<string> apiResourceNames) { var result = new List<ApiResource>(); foreach (var name in apiResourceNames) { if (apiResources.Count(t=>t.Name== name) > 0) { result.Add(apiResources.First(t => t.Name == name)); } } return result; }
FindApiScopesByNameAsync
/// <summary> /// ApiScope 資源 /// </summary> private readonly List<ApiScope> apiScopeResources = new List<ApiScope> { new ApiScope("article.list", "文章-查看"), new ApiScope("article.delete", "文章-刪除"), new ApiScope("user.list", "用戶-查看"), new ApiScope("user.delete", "部門-刪除"), };
/// <summary> /// 通過 名稱 查找符合要求的 ApiScopes /// </summary> /// <param name="scopeNames"></param> /// <returns></returns> public async Task<IEnumerable<ApiScope>> FindApiScopesByNameAsync(IEnumerable<string> scopeNames) { var result = new List<ApiScope>(); foreach (var name in scopeNames) { if (apiScopeResources.Count(t => t.Name == name) > 0) { result.Add(apiScopeResources.First(t => t.Name == name)); } } return result; }
FindApiResourcesByScopeNameAsync
/// <summary> /// 通過 作用域名稱 查找符合要求的 ApiResources /// </summary> /// <param name="scopeNames"></param> /// <returns></returns> public async Task<IEnumerable<ApiResource>> FindApiResourcesByScopeNameAsync(IEnumerable<string> scopeNames) { var result = new List<ApiResource>(); foreach (var name in scopeNames) { foreach (var apiResource in apiResources) { if (apiResource.Scopes.Contains(name) && result.Count(t=>t.Name == name) ==0) { result.Add(apiResource); } } } return result; }
GetAllResourcesAsync
/// <summary> /// 返回所有的資源 /// </summary> /// <returns></returns> public async Task<Resources> GetAllResourcesAsync() { return new Resources(identityResources, apiResources, apiScopeResources); }
修改 Client 的 AllowedScopes
new Client { ClientId = "client2", // 用戶名 密碼 模式 AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, // 用於認證的密碼 ClientSecrets = { new Secret("secret".Sha256()) }, // 客戶端有權訪問的范圍(Scopes) AllowedScopes = { "openid", "profile" , "article.list" , "article.delete" , "user.list" , "user.delete" } }
刪除注入的內存資源服務
PostMan 測試
本文轉載自:https://limitcode.com/detail/606f012fd9118c3cd416879a.html