IdentityServer4实战:持久化 Resource
前言
在前几篇的学习中,我们定义的 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