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

1

2

3

4

5

6

7

/// <summary>

        /// 身份资源

        /// </summary>

        private readonly List<IdentityResource> identityResources = new List<IdentityResource> {

            new IdentityResources.OpenId(),

            new IdentityResources.Profile()

        };

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

/// <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

1

2

3

4

5

6

7

8

9

10

11

/// <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" }

            },

        };

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

/// <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

1

2

3

4

5

6

7

8

9

10

/// <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""部门-删除"),

        };

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

/// <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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

/// <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

1

2

3

4

5

6

7

8

/// <summary>

        /// 返回所有的资源

        /// </summary>

        /// <returns></returns>

        public  async Task<Resources> GetAllResourcesAsync()

        {

            return new Resources(identityResources, apiResources, apiScopeResources);

        }

修改 Client 的 AllowedScopes

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

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 测试

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值