一. 前言
1.业务背景
我们前面尝试了在业务服务器上加IDS4校验,实际上是不合理的, 在生产环境中,业务服务器会有很多个,如果把校验加在每个业务服务器上,代码冗余且不易维护(很多情况下业务服务器不直接对外开放),所以我们通常把校验加在Ocelot网关上,也就是说校验通过了,Ocelot网关才会把请求转发给相应的业务服务器上.(我们这里通常是网关和业务服务器在一个内网中,业务服务器不开放外网)
(和前面:Jwt配合中间件校验流程上是一样的,只不过这里的认证和授权都基于IDS4来做)
PS:关于IDS4服务器,可以配置在网关后面,通过网关转发;
也可以不经网关转发,单独存在, 这里要说明的是,如果经过网关转发,那么对于IDS4而言,只是单纯的转发,不走Ocelot上的校验,其实也很简单,就是不配置AuthenticationProviderKey即可.
2.用到的项目
(1).Case2下的GateWay_Server :网关服务器
(2).Case2下的ID4_Server:认证+授权服务器
(3).GoodsService + OrderService:二者都是资源服务器
(4).PostMan:充当客户端(即第三方应用)
(5).MyClient2:用控制台充当客户端(即第三方应用)
(6).Consul:网关Ocelot已经集成Consul服务发现了,而且资源服务器也已经注册到Consul中了.
二. 核心剖析和测试
1.搭建步骤
(一).启动资源服务器
(1).启动Consul:【consul.exe agent -dev】
(2).启动资源服务器:【dotnet GoodsService.dll --urls="http://*:7001" --ip="127.0.0.1" --port=7001 】
【dotnet OrderService.dll --urls="http://*:7004" --ip="127.0.0.1" --port=7004 】
代码分享:
[Route("api/[controller]/[action]")] [ApiController] public class CatalogController : ControllerBase { [HttpGet] public string GetGoodById1(int id) { var myData = new { status = "ok", goods = new Goods() { id = id, goodName = "apple", goodPrice = 6000, addTime = DateTime.Now } }; var jsonData = JsonHelp.ToJsonString(myData); return jsonData; //返回前端的数据不能直接点出来 } } [Route("api/[controller]/[action]")] [ApiController] public class BuyController : ControllerBase { [HttpPost] public string pOrder1() { return "ok"; } }
(二). GateWay_Server网关的基本配置
(1).Nuget安装包【Ocelot 16.0.1】【Ocelot.Provider.Consul 16.0.1】, 并在ConfigureService和Config中进行配置 services.AddOcelot().AddConsul(); 和 app.UseOcelot().Wait();
(2).Nuget安装包【IdentityServer4.AccessTokenValidation 3.0.1】,用于身份校验.
(3).编写配置文件(OcelotConfig.json),属性改为始终复制,在Program中进行加载;
在配置文件,给GoodsService和OrderService下的节点, 添加 "AuthenticationProviderKey": "OrderServiceKey"/"GoodsServiceKey", 和ConfigureService中的注册进行对应,表示该转发需要走校验.
(把IDS4获取Token的地址也配置进来,但不做校验,也可以不配置进来)
代码分享
//模式三:将Ocelot与consul结合处理,在consul中已经注册业务服务器地址,在Ocelot端不需要再注册了(推荐用法) { "Routes": [ { "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "ServiceName": "GoodsService", //Consul中的服务名称 "LoadBalancerOptions": { "Type": "RoundRobin" //轮询算法:依次调用在consul中注册的服务器 }, "UseServiceDiscovery": true, //启用服务发现(可以省略,因为会默认赋值) "UpstreamPathTemplate": "/GoodsService/{url}", "UpstreamHttpMethod": [ "Get", "Post" ], "AuthenticationOptions": { "AuthenticationProviderKey": "GoodsServiceKey", "AllowedScopes": [] } }, { "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "ServiceName": "OrderService", "LoadBalancerOptions": { "Type": "LeastConnection" //最小连接数算法 }, "UseServiceDiscovery": true, "UpstreamPathTemplate": "/OrderService/{url}", "UpstreamHttpMethod": [ "Get", "Post" ], "AuthenticationOptions": { "AuthenticationProviderKey": "OrderServiceKey", "AllowedScopes": [] } }, //把ID4_Server认证授权服务器也配置进来,但它不再Ocelot层次上加密,单纯的进行转发 { //转发下游(业务服务器)的匹配规则 "DownstreamPathTemplate": "/{url}", //下游请求类型 "DownstreamScheme": "http", //下游的ip和端口,和上面的DownstreamPathTemplate匹配起来 "DownstreamHostAndPorts": [ { "Host": "127.0.0.1", "Port": 7051 } ], //上游(即Ocelot)接收规则 "UpstreamPathTemplate": "/auth/{url}", //上游接收请求类型 "UpstreamHttpMethod": [ "Get", "Post" ] } ], //下面是配置Consul的地址和端口 "GlobalConfiguration": { //对应Consul的ip和Port(可以省略,因为会默认赋值) "ServiceDiscoveryProvider": { "Host": "127.0.0.1", "Port": 8500 } } }