.net core 微服务之 Ocelot 集成 IdentityServer4

为什么集成在Ocelot中

在上一篇文章中,我们并没有将认证授权集成在Ocelot中,在生产环境中,如果我们每个服务都添加了认证授权,那么在实际部署中肯定会生成很多的配置,就会相对于麻烦。

所以我们就把IdentityServer4加到网关中,客户端的请求通过网关就会进行身份证验证,当网关的身份验证通过之后就会把请求转发给服务集群中,集群就不需要进行身份验证了

 

项目示例

1. 在网关中引入包

IdentityServer4.AccessTokenValidation

2. 注入服务,这里要在Idr4中新增一个网关的api资源名称,我比较懒,就用的上篇文章创建好了的名称。

注意,这里要给一个Sceme名称,随便取一个就行,方便Ocelot识别

//添加idr4权限
services.AddAuthentication("Bearer")
    //给当前授权随便起个名称,方便集成到Ocelot里面去
    .AddIdentityServerAuthentication("OcelotScheme",options =>
    {
        options.Authority = "http://localhost:2000"; //授权地址
        options.RequireHttpsMetadata = false; 
        options.ApiSecret = "testcode";  //网关资源API秘钥
        options.ApiName = "signalrapi";  //网关的资源API名称
    });

3. 新加一个测试的Ocelot配置文件 ocelot.Idr4.json , 在之前的路由(ReRoutes)中新增一个认证参数( AuthenticationOptions )配置就行了,这里的 AuthenticationProviderKey 配置为刚才注册服务时随便取的那个Scheme名称

{
  "ReRoutes": [
    {
      "DownstreamPathTemplate": "/ConsulHealthCheck/{action}", //下游转发接口
      "DownstreamScheme": "http",


      "ServiceName": "consualapi",
      "LoadBalancerOptions": { //负载均衡配置
        "Type": "LeastConnection" //“轮询”算法  可以配置其他的
      },
      "UpstreamPathTemplate": "/GateWay/{action}", //上游接口地址
      "UpstreamHttpMethod": [ "Get", "Post" ], //限制网关http请求方式
      //集成idr4认证
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "OcelotScheme",  //配置startup中服务名称
        "AllowedScopes": []
      }
    }
  ],

  "GlobalConfiguration": {
    "ServiceDiscoveryProvider": {
      "Host": "localhost",
      "Port": 8500,
      "Type": "Consul"
    },
    "RateLimitOptions": {
      "DisableRateLimitHeaders": false,
      "QuotaExceededMessage": "Custom Tips",
      "HttpStatusCode": 999,
      "ClientIdHeader": "Test"
    }
  }
}

4. 在Consul服务中新增一个接口测试

/// <summary>
/// 当前登录用户信息
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
[HttpGet("UserInfo")]
public async Task<IActionResult> UserInfo()
{
    //根据网关转发过来的token去认证服务获取用户信息
    var accessToken=HttpContext.Request.Headers["Authorization"].ToString();
    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri("http://localhost:2000");
    client.DefaultRequestHeaders.Add("Authorization", accessToken);
    var userinfo = await client.GetAsync("/connect/userinfo");

    return Ok($"你正在调用端口号为{Request.HttpContext.Connection.LocalPort}的方法, 用户信息为 { userinfo.Content.ReadAsStringAsync().Result}");
}

运行效果

 

Ocelot实现 动态路由

 如果添加很多个服务,那么会产生很多的Ocelot.xx.json文件,这里就使用动态路由,只有一个Ocelot.json文件。

1. 添加一个动态路由的Json文件( DynamicReOcelot.json ),ReRoutes 和  Aggregates 一定要为空

{
  "ReRoutes": [],
  "Aggregates": [],
   //单个服务配置限流
  "DynamicReRoutes": [
    {
      "ServiceName": "consualapi",
      "RateLimitRule": {
        "ClientWhitelist": [],
        "EnableRateLimiting": true,
        "Period": "1s",
        "PeriodTimespan": 3000,
        "Limit": 3
      }
    }
  ],
  "GlobalConfiguration": {
    "RequestIdKey": null,
    "ServiceDiscoveryProvider": {
      "Host": "localhost",
      "Port": 8500,
      "Type": "Consul",
      "Token": null,
      "ConfigurationKey": null
    },
    "RateLimitOptions": {
      "ClientIdHeader": "ClientId",
      "QuotaExceededMessage": null,
      "RateLimitCounterPrefix": "ocelot",
      "DisableRateLimitHeaders": false,
      "HttpStatusCode": 429
    },
    "QoSOptions": {
      "ExceptionsAllowedBeforeBreaking": 0,
      "DurationOfBreak": 0,
      "TimeoutValue": 0
    },
    "BaseUrl": null,
    "LoadBalancerOptions": {
      "Type": "LeastConnection",
      "Key": null,
      "Expiry": 0
    },
    "DownstreamScheme": "http",
    "HttpHandlerOptions": {
      "AllowAutoRedirect": false,
      "UseCookieContainer": false,
      "UseTracing": false
    },
    //集成idr4认证
    "AuthenticationOptions": {
      "AuthenticationProviderKey": "OcelotScheme", //配置startup中服务名称
      "AllowedScopes": []
    }
  }
}

 

 

 

2. 加载动态路由配置文件,替代之前的Ocelot.json文件

 public static IHostBuilder CreateHostBuilder(string[] args) =>
     Host.CreateDefaultBuilder(args)
         .ConfigureWebHostDefaults(webBuilder =>
         {
             webBuilder.UseStartup<Startup>();
             webBuilder.ConfigureAppConfiguration((hostingContext, config) =>
             {
                 // 1、加载ocelot配置文件
                 //config.AddJsonFile("ocelot.json");
                 

                 //2. 动态加载多个服务配置
                 //config
                 //    .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
                 //    .AddJsonFile("appsettings.json", true, true)
                 //   .AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true)
                 //   .AddOcelot(hostingContext.HostingEnvironment)
                 //  .AddEnvironmentVariables();

                 //3. 动态路由 
                 config.AddJsonFile("DynamicReOcelot.json");
             });
         });

请求效果:

 

 

 

注意,这里解析逻辑:

1. 客户端发起请求到 http://localhost:7000 的网关

2. 网关在consul服务发现中找到对应的服务名称,后随机返回一个服务名称的地址,这里是 http://localhost:5004

3. 请求的路径除了第一个是服务的名字,后面都是网关下游请求服务的地址,这里是  /ConsulHealthCheck/userinfo

4. 所以实际的请求是 : http://localhost:5004/ConsulHealthCheck/userinfo

 

 

 

 

 

 

posted @ 2023-02-15 16:25  Joni是只狗  阅读(284)  评论(0编辑  收藏  举报