• 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

  • 相关阅读:
    Fibonacci数列2
    足球队
    网页导航
    Catenyms
    某种密码
    大逃亡
    球的序列
    圆内三角形统计
    最小平方数

  • 原文地址:https://www.cnblogs.com/limitcode/p/14639521.html
Copyright © 2020-2023  润新知