IdentityServer4的最佳使用
简介
本人做微服务项目也有一段时间了,在微服务中让我感触颇深的就是这个IdentityServer4了,ID4(IdentityServer4的简称)中涉及的概念颇多,本文不谈概念(我怕读者没耐心看下去),在这分享下我个人的使用心得。
目录
1. ID4简介
2. ID4使用
ID4简介
相信大家都知道面向对象中的封装(把通用的功能封装起来,减少程序中大量重复代码),我们知道在一个单体系统中有很多的重复模块,例如:身份认证、权限控制检查等,在单体系统中,这些都可以使用aop统一在一个地方控制。而在分布式系统,每个系统都需要进行身份认证、权限检查等。这时,每个系统都得写一套同样的代码来进行这些控制,我们能不能像单体系统那样在一个地方进行这些流程呢?这时我们可以使用IdentityServer4来实现。
IdentityServer4是一个集成 身份认证和授权 的组件,使用OpenId Connect(身份识别框架) 和 Auth2.0(授权框架)来进行身份认证和授权的。
ID4使用
我这里只列出几个主要的类,其它,可以下载项目来看。关于如何使用,代码有点多,我比较懒,就没怎么讲解,感兴趣的小伙伴可以加个QQ:1983702356 来讨论下。
项目地址: https://github.com/MapleWithoutWords/IdentityServer4Demo
(注意:下载项目后,记得把数据库链接字符串改下)项目环境:
- .net core 2.2
- IdentityServer 2.5
- Mysql 8
项目结构:

WEBAPPLICATION1 (IDENTITYSERVER4)项目,安装 INSTALL-PACKAGE IDENTITYSERVER4 -VERSION 2.5.0,
以下几个类比较关键
Config.cs。主要是获取身份资源
1
2
3
4
5
6
7
8
9
10
11
12public class Config
{
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(), //必须要添加,否则报无效的 scope 错误
new IdentityResources.Profile(),
new IdentityResources.Email()
};
}
}TestClientStore.cs 加载IdentityServer4的client
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37/// <summary>
/// 加载IdentityServer4的client
/// </summary>
public class TestClientStore : IClientStore
{
/// <summary>
/// Service层中的一个接口
/// </summary>
public IClientService ClientSvc { get; set; }
public TestClientStore(IClientService ClientSvc)
{
this.ClientSvc = ClientSvc;
}
public async Task<Client> FindClientByIdAsync(string clientId)
{
var dto = await ClientSvc.FindClientByIdAsync(clientId);
if (dto==null)
{
return null;
}
var scopes = dto.APIResources.Select(e => e.Name).ToList();
scopes.Add(IdentityServerConstants.StandardScopes.OpenId);
scopes.Add(IdentityServerConstants.StandardScopes.Profile);
return new Client
{
ClientId = dto.Client.Id,//API账号、客户端Id
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets =
{
new Secret(dto.Client.Secret.Sha256())//秘钥
},
AllowedScopes = scopes//这个账号支持访问哪些应用
};
}
}TestReourceStore.cs,加载IdentityServer的APIResource
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39/// <summary>
/// 加载IdentityServer的APIResource
/// </summary>
public class TestReourceStore : IResourceStore
{
public IApiResourceService resourceSvc { get; set; }
public TestReourceStore(IApiResourceService resourceSvc)
{
this.resourceSvc = resourceSvc;
}
public async Task<ApiResource> FindApiResourceAsync(string name)
{
var entity = await resourceSvc.GetByNameAsync(name);
return new ApiResource(entity.Name,entity.DisplayName);
}
public async Task<IEnumerable<ApiResource>> FindApiResourcesByScopeAsync(IEnumerable<string> scopeNames)
{
var list = await resourceSvc.GetDatasByNamesAsync(scopeNames);
return list.Select(e=>new ApiResource(e.Name,e.DisplayName));
}
public async Task<IEnumerable<IdentityResource>> FindIdentityResourcesByScopeAsync(IEnumerable<string> scopeNames)
{
return Config.GetIdentityResources().Where(e => scopeNames.Contains(e.Name)).ToList();
}
public async Task<Resources> GetAllResourcesAsync()
{
var list = await resourceSvc.GetNoramlAll();
var resouces = list.Select(e => new ApiResource(e.Name, e.DisplayName)).ToList();
return new Resources
{
ApiResources = resouces
};
}
}TestResourceOwnerPasswordValidator.cs,IdentityServer4登录验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34/// <summary>
/// IdentityServer4登录验证
/// </summary>
public class TestResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
public IUserService UserSvc { get; set; }
public TestResourceOwnerPasswordValidator(IUserService UserSvc)
{
this.UserSvc = UserSvc;
}
public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
string account = context.UserName;
string pwd = context.Password;
var loginResult = await UserSvc.Login(account, pwd);
if (loginResult == null)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "invalid custom credential");
return;
}
context.Result = new GrantValidationResult(
subject: context.UserName,
authenticationMethod: "custom",
claims: new Claim[] {
new Claim("Name",context.UserName),
new Claim("UserId",loginResult.Id),
new Claim("Roles","Admin,Contact"), //模拟获取登录用户的角色信息
new Claim("Premissions","List,Delete") //模拟获取登录用户的权限信息
});
}
}ProfileService.cs,用户信息
1
2
3
4
5
6
7
8
9
10
11
12
13public class ProfileService : IProfileService
{
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var claims = context.Subject.Claims.ToList();
context.IssuedClaims = claims.ToList();
}
public async Task IsActiveAsync(IsActiveContext context)
{
context.IsActive = true;
}
}
- Startup类
1 |
public class Startup |
- WebApplication3 API项目,修改Startup,并添加一个控制器,在方法上打上一个标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:9500";//identity server 地址
options.RequireHttpsMetadata = false;
});
string conStr = Configuration["connectionString"];
services.AddDbContext<TestDbContext>(options =>
{
options.UseMySql(conStr);
});
///依赖注入Service层
AddSigletons(services);
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
public void AddSigletons(IServiceCollection services)
{
var assem = Assembly.Load("Test.Service");
var list = assem.GetTypes().Where(e => e.IsAbstract == false && typeof(ISignFac).IsAssignableFrom(e));
foreach (var instanType in list)
{
foreach (var item in instanType.GetInterfaces())
{
services.AddSingleton(item, instanType);
}
}
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
}
}

运行CONSOLEAPP1控制台项目, 生成数据库,添加几条数据

运行效果
在 WebApplication1 目录下运行cmd命令 dotnet run ,启动IdentitServer4,端口是9500


运行项目 WebApplication3 ,端口是5000
当我们直接调用 WebApplication3 API中的方法时,发现返回状态码为 401

请求Id4,复制返回的 access_token

再请求WebApplication3 API,并在报文头带上token

结束语
个人认为我这种使用方式和其它使用方式最大的好处就是,可以写一个IdentityServer4的Client、APIResource增删改查,然后因为每次请求的时候都是从数据库读取数据的,如果数据被修改了,会立即生效。
IdentityServer4的最佳使用的更多相关文章
- IdentityServer4关于多客户端和API的最佳实践【含多类型客户端和API资源,以及客户端分组实践】【下】
经过前两篇文章你已经知道了关于服务器搭建和客户端接入相关的基本资料,本文主要讲述整个授权系统所服务的对象,以ProtectApi资源为演示 目标: 1)实现多资源服务器针对请求的token校验,接入I ...
- IdentityServer4实战 - 谈谈 JWT 的安全策略
一.前言 众所周知,IdentityServer4 默认支持两种类型的 Token,一种是 Reference Token,一种是 JWT Token .前者的特点是 Token 的有效与否是由 To ...
- ASP.NET Core身份认证服务框架IdentityServer4(2)-整体介绍
一.整体情况 现代应用程序看起来更像这个: 最常见的相互作用: 浏览器与Web应用程序的通信 Browser -> Web App Web应用程序与Web API通信 基于浏览器的应用程序与We ...
- IdentityServer4 中文文档 -1- (简介)背景
IdentityServer4 中文文档 -1- (简介)背景 原文:http://docs.identityserver.io/en/release/intro/big_picture.html 目 ...
- IdentityServer4 中文文档 -8- (快速入门)设置和概览
IdentityServer4 中文文档 -8- (快速入门)设置和概览 原文:http://docs.identityserver.io/en/release/quickstarts/0_overv ...
- IdentityServer4中文文档
欢迎IdentityServer4 IdentityServer4是ASP.NET Core 2的OpenID Connect和OAuth 2.0框架. 它在您的应用程序中启用以下功能: 认证即服务 ...
- 【IdentityServer4文档】- 启动和概览
启动和概览 有两种基本的方式来启动一个新的 IdentityServer 项目: 从空项目开始(从头开始) 从 Visual Studio 的 ASP.NET Identity 模板开始 假如您从头开 ...
- 【IdentityServer4文档】- 整体情况
整体概况 大多数现代应用程序看起来或多或少像这样: 最常见的交互是: 浏览器与 Web 应用程序进行通信 Web 应用程序与 Web API 进行通信(有时是Web应用程序自己发起,有时代表用户发起) ...
- IdentityServer4实战 - 谈谈 JWT Token 的安全策略
原文:IdentityServer4实战 - 谈谈 JWT Token 的安全策略 一.前言 众所周知,IdentityServer4 默认支持两种类型的 Token,一种是 Reference To ...
- asp.net core IdentityServer4 概述
概览 现代应用程序看上去大都是这样的: 最常见的交互是: 浏览器与Web应用程序通信 Web应用程序与Web API通信(有时是独立的,有时是代表用户的) 基于浏览器的应用程序与Web API通信 本 ...
随机推荐
- Beats:使用 Filebeat 导入 JSON 格式的日志文件
转载自:https://blog.csdn.net/UbuntuTouch/article/details/108504014 在今天的文章中,我来用另外的一种方式来展示如何导入一个 JSON 格式的 ...
- numpy中的一些常用的关键字用法
1.np.full() 原型:numpy.full(shape, fill_value, dtype=None, order='C') eg: 2.np.flatten():该函数返回一个折叠成一维的 ...
- 代码随想录第二天| 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II
2022/09/22 第二天 第一题 这题我就直接平方后排序了,很无脑但很快乐啊(官方题解是双指针 第二题 滑动窗口的问题,本来我也是直接暴力求解发现在leetCode上超时,看了官方题解,也是第一次 ...
- SpringBoot(五) - Java8 新特性
1.Lambda表达式 Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递).使用它可以写出更简洁.更灵活的代码.作为一种更紧凑的代码风 ...
- hyperf-搭建初始化
官方文档* https://hyperf.wiki/2.0/#/README 初步搭建1. 安装项目 composer create-project hyperf/hyperf-skeleton 2. ...
- JS复制粘贴效果
话不多说.直接上代码 HTML: 1 <div> 2 老师入会密码:<input type="text" id="tPass"> < ...
- JUC(10)深入理解CAS和ABA
文章目录 1.CAS 2.原子引用解决ABA问题,版本号.修改后,可以看到 1.CAS package com.cas; import java.util.concurrent.atomic.Atom ...
- 服务器之Apollo单机部署(快速安装)
部署Apollo apollo单机部署(快速安装) Apollo官网:https://www.apolloconfig.com/#/zh/deployment/quick-start-docker 官 ...
- Docker之介绍与安装
Docker 说明 本章,我们主要从Docker简介.Docker中几个核心概念和Docker安装这几个方面对Docker进行介绍! 1. Docker 简介 1.1. 什么是 Docker Dock ...
- .Net Core - 使用事务IDbtransaction操作DBData
New一个流程 获取数据库连接字符串,实例化SqlConnection 打来数据库连接 Begin当前连接的事务(IDbTransaction) 操作数据库(操作数据库的时候一定要使用当前连接和事务修 ...