爲什麼集成在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