天天看点

IdentityServer4实战:持久化 Resource前言IdentityServer4 中 Resource 概念IResourceStore 接口CustomerResourceStore 实现

前言

在前几篇的学习中,我们定义的 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 持久化存储和读取。

IdentityServer4实战:持久化 Resource前言IdentityServer4 中 Resource 概念IResourceStore 接口CustomerResourceStore 实现

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"

}

}

删除注入的内存资源服务

IdentityServer4实战:持久化 Resource前言IdentityServer4 中 Resource 概念IResourceStore 接口CustomerResourceStore 实现

PostMan 测试

IdentityServer4实战:持久化 Resource前言IdentityServer4 中 Resource 概念IResourceStore 接口CustomerResourceStore 实现
IdentityServer4实战:持久化 Resource前言IdentityServer4 中 Resource 概念IResourceStore 接口CustomerResourceStore 实现