微服务项目整合Ocelot+IdentityServer4
项目搭建肯定少不了认证和授权,传统的单体应用基于cookie和session来完成的。
因为http请求是无状态的,每个请求都是完全独立的,服务端无法确认当前请求之前是否登陆过。所以第一次请求(登录),服务器会返回SessionID 返回给浏览器,浏览器会存于Cookie中,下次请求带上SessionID.这样服务端每次拿到SessionID后就去找是否存在对应的会话信息,判断过期及后续操作等......
这个授权操作适用于MVC的项目,在分布式的项目中就不行了。session信息存在不同的服务实例中,在集群应用中一般都采取轮询机制,A服务实例保存了session信息,B服务实例上没有这个信息,请求达到B服务是会返回401的code信息,但是已经登录过,所以问题就暴露了......
针对此问题,可采取Session共享:将session信息存入redis中,每个服务实例都从redis中拿session信息。 会话粘滞:这个可以依靠nginx实现,也就是请求从登录开始,每个请求都会访问同一个服务实例。第一次登录访问的服务实例,之后每一次都会访问这个服务实例。但是这个就脱离了负载均衡策略,用可能100个请求,80个都是A服务接收......
OAuth2.0(协议)
数据所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌,用来代替密码,供第三方应用使用。
规范了下授权的流程,五种模式:
客户端凭证(client credentials)
密码式(password)
隐藏式(implicit)
授权码(authorization-code)
混合式(Hybrid)
IdentityServer4
IdentityServer4(认证授权的中间件)是在.Net Core微服务架构中首选的授权认证解决方案。为Asp.Net Core量身定制实现了OpenId Connect和OAuth2.0协议(规范)。

使用IdentityServer4构建鉴权中心
引入NuGet包:IdentityServer4
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseIdentityServer();//添加认证中间件 app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(); //客户端模式--怎么执行Ids4
services.AddIdentityServer()//怎么处理
.AddDeveloperSigningCredential()//默认开发者证书,每一次启动证书都会刷新
.AddInMemoryClients(InitConfig.GetClients())//InMemory 内存模式
.AddInMemoryApiResources(InitConfig.GetApiResources());//能访问啥资源
}
/// <summary>
/// 自定义管理信息
/// </summary>
public class InitConfig
{
/// <summary>
/// 定义ApiResource
/// 这里的资源(Resource)指的就是管理的Api
/// </summary>
/// <returns></returns>
public static IEnumerable<ApiResource> GetApiResources()
{
return new[]
{
new ApiResource("UserApi","用户获取Api")
};
} /// <summary>
/// 定义验证条件的Client
/// </summary>
/// <returns></returns>
public static IEnumerable<Client> GetClients()
{
return new[]
{
new Client
{
ClientId="authentication",//客户端唯一标识
ClientSecrets=new[]{new Secret("auth123456".Sha256()) },//客户端密码进行加密
//AllowedGrantTypes=GrantType.ClientCredentials,//验证模式
AllowedGrantTypes={GrantType.ClientCredentials },//验证模式
AllowedScopes=new []{ "UserApi"},//作用域,可以访问的资源,该用户可访问哪些Api
Claims=new List<Claim>()
{
new Claim(IdentityModel.JwtClaimTypes.Role,"admin"),
new Claim(IdentityModel.JwtClaimTypes.NickName,"江北"),
new Claim("Email","**********@163.com"),
}
}
};
}
}
使用Postman测试:

在服务实例中加入鉴权中间件,引入NuGet包 IdentityServer4.AccessTokenValidation,并在需要鉴权的接口上面标识[Authorize]特性
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
}); app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthentication();//鉴权,没有鉴权,授权是没有意义的
app.UseAuthorization();//授权 app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
}); //启动时注册,且注册一次
this.Configuration.ConsulExtend();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(m =>
{
m.Authority = "http://localhost:7200";//Ids的地址
m.ApiName = "GetCustomerUser";
m.RequireHttpsMetadata = false;
});
}
直接访问会报401的错误

先去请求鉴权中心,拿到Token后,带上Token请求

如果报下面这个错误,可能是作用域的问题,你请求的Api和可访问的Api集合对不上

针对上面的过程,我们理一理流程。首先我们在A鉴权服务中心请求获取Token,拿到Token后去请求B实例服务上的接口。A鉴权中心和B服务实例并没有进行交互,B服务实例怎样识别Token,这之间是怎样的验证的呢?
其实这里有一个加密算法
非对称可逆加密,加密Key和解密Key不同(一对儿),而且无法推导
加密--content--result(原文加密为密文)
解密--result--content(通过密文解密为原文) 公开解密key-公钥
私藏加密key-私钥
再来走一下流程,首先在A鉴权中心验证登录,并将获取的用户信息用私钥加密作为Token进行响应返回。所以在Token中不适合存一些敏感信息。但是有一点可以保证,只要是用这个私钥配对的公钥解开的Token,那么一定是由这个私钥加密的,就证明这个Token是合法的,可通过的。
那什么时候拿到公钥?第一次.没错,在第一次请求到达B服务实例的时候,B服务实例会去A鉴权中心请求拿到公钥。之后就不在需要和A鉴权中心进行交互,除非B服务实例重新启动。
既然是微服务架构,所以鉴权也统一走网关,不然每一个服务实例都要写一套鉴权的代码。因为走网关鉴权,所以所有的api都要授权才能访问。
在网关服务中引入包 IdentityServer4.AccessTokenValidation
public void ConfigureServices(IServiceCollection services)
{
#region Identity4
var authenticationProviderKey = "Gatewaykey";
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(authenticationProviderKey, m =>
{
m.Authority = "http://localhost:7200";//Ids的地址,获取公钥
m.ApiName = "GetCustomerUser";
m.RequireHttpsMetadata = false;
m.SupportedTokens = SupportedTokens.Both;
});
#endregion
}
//*************************Consul+Cache+超时+限流+熔断+降级*****************************
"Routes": [
{
//GeteWay转发=>Downstream
"DownstreamPathTemplate": "/api/{url}", //服务地址--url变量
"DownstreamScheme": "http",
//http://localhost:6299/T5/User/GetCustomerUser
"UpstreamPathTemplate": "/T5/{url}", //网关地址--url变量 冲突的还可以加权重Priority
"UpstreamHttpMethod": [ "Get", "Post" ],
"UseServiceDiscovery": true, //使用服务发现
"ServiceName": "MicroserviceAttempt", //Consul服务名称
"LoadBalancerOptions": {
"Type": "RoundRobin" //轮询 //"LeastConnection":最少连接数服务器 "NoloadBalance":不负载均衡 "CookieStickySession":会话粘滞
},
//使用缓存
"FileCacheOptions": {
"TtlSeconds": , //过期时间
"Region": "UserCache" //可以调用Api清理
},
//限流 张队长贡献的
"RateLimitOptions": {
"ClientWhitelist": [ "Microservice", "Attempt" ], //白名单 ClientId区分大小写
"EnableRateLimiting": true,
"Period": "1s", //5m 1h 1d
"PeriodTimespan": , //多少秒之后客户端可以重试
"Limit": //统计时间段内允许的最大请求数
},
//鉴权
"AuthenticationOptions": {
"AuthenticationProviderKey": "Gatewaykey",
"AllowedScopes": []
},
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": , //熔断之前允许多少个异常请求
"DurationOfBreak": , //熔断的时间,单位为ms.超过这个时间可再请求
"TimeoutValue": //如果下游请求的处理时间超过多少则将请求设置为超时 默认90秒
}
}
],
"GlobalConfiguration": {
"BaseUrl": "http://127.0.0.1:6299",
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": ,
"Type": "Consul" //由Consul提供服务发现,每次请求去Consul
},
"RateLimitOptions": {
"QuotaExceededMessage": "Customize Tips!", //限流时返回的消息
"HttpStatusCode": //限流时返回的code
}
//"ServiceDiscoveryProvider": {
// "Host": "localhost",
// "Port": 8500,
// "Type": "PollConsul", //由Consul提供服务发现,每次请求去Consul
// "PollingInterval": 1000//轮询Consul,评率毫秒--down是不知道的
//}
}
//*************************Consul+Cache+超时+限流+熔断+降级*****************************
启动鉴权服务、网关、服务实例

Postman测试

当然,还不是很完善,还要加策略授权模式。后期我会再补充
如有不当,望包涵!
微服务项目整合Ocelot+IdentityServer4的更多相关文章
- .Net Core 商城微服务项目系列(一):使用IdentityServer4构建基础登录验证
这里第一次搭建,所以IdentityServer端比较简单,后期再进行完善. 1.新建API项目MI.Service.Identity,NuGet引用IdentityServer4,添加类InMemo ...
- .NET Core 微服务—API网关(Ocelot) 教程 [三]
前言: 前一篇文章<.NET Core 微服务—API网关(Ocelot) 教程 [二]>已经让Ocelot和目录api(Api.Catalog).订单api(Api.Ordering)通 ...
- .NET Core微服务之基于Ocelot实现API网关服务
Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.啥是API网关? API 网关一般放到微服务的最前端,并且要让API 网关变成由应用所发起的每个请求的入口.这样就可以明显的简化客户端 ...
- .NET Core微服务二:Ocelot API网关
.NET Core微服务一:Consul服务中心 .NET Core微服务二:Ocelot API网关 .NET Core微服务三:polly熔断与降级 本文的项目代码,在文章结尾处可以下载. 本文使 ...
- .NET Core 微服务—API网关(Ocelot) 教程 [二]
上篇文章(.NET Core 微服务—API网关(Ocelot) 教程 [一])介绍了Ocelot 的相关介绍. 接下来就一起来看如何使用,让它运行起来. 环境准备 为了验证Ocelot 网关效果,我 ...
- SpringCloud(1)---基于RestTemplate微服务项目案例
基于RestTemplate微服务项目 在写SpringCloud搭建微服务之前,我想先搭建一个不通过springcloud只通过SpringBoot和Mybatis进行模块之间额通讯.然后在此基础上 ...
- Docker部署golang微服务项目
这篇博客是为了记录一下部署步骤. 因为实训需要,我要在服务器上用docker部署我们小组的微服务项目.我们的微服务有Gateway,User,Scene,Device四个部分,分别占用不同的端口,其中 ...
- docker微服务部署之:三,搭建Zuul微服务项目
docker微服务部署之:二.搭建文章微服务项目 一.新增demo_eureka模块,并编写代码 右键demo_parent->new->Module->Maven,选择Module ...
- docker微服务部署之:二、搭建文章微服务项目
docker微服务部署之:一,搭建Eureka微服务项目 一.新增demo_article模块,并编写代码 右键demo_parent->new->Module->Maven,选择M ...
随机推荐
- c++输出左右对齐设置
#include<iostream> int main(){ using std::cout; cout.setf(std::ios::left); int w = cout.width( ...
- 线程_GIL最简单的例子
#解决多进程死循环 import multiprocessing def deadLoop(): while True: print("Hello") pass if __name ...
- ASP.NET Core 监听SQL Server数据库的实时信息
1.开发环境: 开发工具:Visual Studio 2019 数据库:SQL Server2012 开发环境:.Net Core 3.1 2.使用技术: Signalr:实现消息推送 SqlDepe ...
- Python语言及其应用 中文pdf完整版|网盘下载内附提取码
点击此处下载提取码:7cvm <Python语言及其应用>介绍Python 语言的基础知识及其在各个领域的具体应用,基于新版本3.x.书中首先介绍了Python 语言的一些基本知识,然后介 ...
- luogu P4929 【模板】舞蹈链 DLX
LINK:舞蹈链 具体复杂度我也不知道 但是 搜索速度极快. 原因大概是因为 每次检索的时间少 有一定的剪枝. 花了2h大概了解了这个东西 吐槽一下题解根本看不懂 只能理解大概的想法 核心的链表不太懂 ...
- odoo自定义模块项目结构,odoo自定义模块点安装不成功解决办法
如图所示:在odoo源码的根目录中创建自己的项目文件(project) 在odoo.conf配置文件中的addons_path路径中加入自己项目的文件夹路径,推荐使用绝对路径 addons_path ...
- Spark中直接操作HDFS
Spark作为一个基于内存的大数据计算框架,可以和hadoop生态的资源调度器和分布式文件存储系统无缝融合.Spark可以直接操作存储在HDFS上面的数据: 通过Hadoop方式操作已经存在的文件目录 ...
- jsp应用-实现用户登陆功能
项目结构 1.login.jsp 这个没什么好说的,把表单提交到校验页面进行校验 2.首先获取request域中user,password,然后进行校验,校验成功把信息存入session域,然后转发到 ...
- 数据库允许空值(null),往往是悲剧的开始
原文: 58沈剑 架构师之路 https://mp.weixin.qq.com/s/XRSPITgWWK-2Ee-cSIqw1w 数据库字段允许空值,会遇到一些问题,此处包含的一些知识点,和大 ...
- SparkBench安装使用入门
SparkBench安装以及快速开始 欢迎关注我的GitHub~ 本指南假定已经可以正常使用Spark 2.x,并且可以访问安装它的系统. 系统环境 CentOS 7.7.1908 Ambari-Sp ...