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通信 本 ...
随机推荐
- k8s控制器理解
DaemonSet 一个DaemonSet对象能确保其创建的Pod在集群中的每一台(或指定)Node上都运行一个副本.如果集群中动态加入了新的Node,DaemonSet中的Pod也会被添加在新加入N ...
- Failed to find a valid digest in the 'integrity' attribute for resource
一.Bootstrap 引入报错 在使用bootstrap过程中发现无法使用下拉导航栏,或者是显示不出效果. Failed to find a valid digest in the 'integr ...
- WinDbg Preview安装以及符号表配置
1.安装WinDbgPreview 在Microsoft Store直接搜索windbg就可以下载. 2.配置符号服务器 2.1 符号 符号是方便调试程序的文件,通常是pdb文件.一个模块(可执行程序 ...
- 在开发中关于javaweb中的路径问题小结
转自http://blog.csdn.net/yinyuehepijiu/article/details/9136117 在javaweb项目中添加配置文件,满足连接数据库配置参数以及其他自定义参数存 ...
- Java 求解自幂数(水仙花数)
什么是自幂数 如果在一个固定的进制中,一个 n 位自然数等于自身各个数位上数字的 n 次幂之和,则称此数为自幂数. 例如:在十进制中,153 是一个三位数,各个数位的3次幂之和为 1^3+5^3+3^ ...
- [Err] 1052 - Column ‘roleId‘ in where clause is ambiguous
1.先看错误的sql语句: select a.authName from roles as r,authority as a,role_ah as ra where ra.roleId=r.roleI ...
- NLP之基于logistic回归的文本分类
数据集下载: 链接:https://pan.baidu.com/s/17EL37CQ-FtOXhtdZHQDPgw 提取码:0829 逻辑斯蒂回归 @ 目录 逻辑斯蒂回归 1.理论 1.1 多分类 1 ...
- CSS 渐变锯齿消失术
在 CSS 中,渐变(Gradient)可谓是最为强大的一个属性之一. 但是,经常有同学在使用渐变的过程中会遇到渐变图形产生的锯齿问题. 何为渐变锯齿? 那么,什么是渐变图形产生的锯齿呢? 简单的一个 ...
- nrf9160 做modem—— 连接云(接入方式MQTT)
今天测试把nrf9160作为modem的例程Serial LTE Modem程序(后面简称slm),何为做modem,通俗来说就是将nrf9160作为无线模块,主控由其余MCU做,主控通过AT命令控制 ...
- .NET 零开销抽象指南
背景 2008 年前后的 Midori 项目试图构建一个以 .NET 为用户态基础的操作系统,在这个项目中有很多让 CLR 以及 C# 的类型系统向着适合系统编程的方向改进的探索,虽然项目最终没有面世 ...