上一章已經簡單的介紹了ocelot的使用了,可是網關暴露的接口若是什麼人都能訪問的話安全性就過低啦。因此咱們須要去鑑權和認證。這裏咱們使用identityServer4給咱們的網關來鑑權認證。json
咱們建立一個identity的服務來用於令牌的發放和鑑權。下圖是個人項目結構。
Api_Gatewat端口:5000
Api_A端口:5001
Api_B端口:5002
IdentityServer端口:5003api
經過nuget添加IdentityServer4的包,也能夠經過程序包管理控制檯執行如下命令Install-Package IdentityServer4
。安全
添加一個Congif文件。app
using System.Collections.Generic; using IdentityModel; using IdentityServer4; using IdentityServer4.Models; namespace IdentityServer { public static class Config { public static IEnumerable<IdentityResource> GetIdentityResourceResources() { return new List<IdentityResource> { new IdentityResources.OpenId(), //必需要添加,不然報無效的scope錯誤 }; } // scopes define the API resources in your system public static IEnumerable<ApiResource> GetApiResources() { //可訪問的API資源(資源名,資源描述) return new List<ApiResource> { new ApiResource("Api_A", "Api_A"), new ApiResource("Api_B", "Api_B") }; } public static IEnumerable<Client> GetClients() { return new List<Client> { new Client { ClientId = "client_a", //訪問客戶端Id,必須惟一 //使用客戶端受權模式,客戶端只須要clientid和secrets就能夠訪問對應的api資源。 AllowedGrantTypes = GrantTypes.ClientCredentials, ClientSecrets = { new Secret("secret".Sha256()) }, AllowedScopes = { "Api_A",IdentityServerConstants.StandardScopes.OpenId,IdentityServerConstants.StandardScopes.Profile } }, new Client { ClientId = "client_b", ClientSecrets = new [] { new Secret("secret".Sha256()) }, AllowedGrantTypes = GrantTypes.ClientCredentials, AllowedScopes = { "Api_B",IdentityServerConstants.StandardScopes.OpenId,IdentityServerConstants.StandardScopes.Profile } } }; } } }
添加兩個API資源,而且添加兩個客戶端分別去訪問不一樣資源。ide
在 Startup
中的 ConfigureServices
中配置IdentityServer服務。ui
public void ConfigureServices(IServiceCollection services) { services.AddIdentityServer() .AddDeveloperSigningCredential() .AddInMemoryApiResources(Config.GetApiResources()) .AddInMemoryClients(Config.GetClients()); }
在 Configure
中把IdentityServer放入http管道中。spa
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseIdentityServer(); }
經過nuget添加IdentityServer4.AccessTokenValidation的包,也能夠經過程序包管理控制檯執行如下命令 Install-Package IdentityServer4.AccessTokenValidation
code
IdentityServer4.AccessTokenValidation - 用於驗證IdentityServer4中的JWT和引用令牌orm
在 Startup
的 ConfigureServices
中分別註冊兩個認證方案 Configure
中配置IdentityServer服務。token
public void ConfigureServices(IServiceCollection services) { services.AddAuthentication() .AddJwtBearer("Api_A", i => { i.Audience = "Api_A"; i.Authority = "http://localhost:5003"; i.RequireHttpsMetadata = false; }).AddJwtBearer("Api_B", y => { y.Audience = "Api_B"; y.Authority = "http://localhost:5003"; y.RequireHttpsMetadata = false; }); services.AddOcelot(new ConfigurationBuilder() .AddJsonFile("configuration.json") .Build()); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseOcelot(); app.UseAuthorization(); }
並修改ocelot配置文件,在Routes中添加受權信息
{ "ReRoutes": [ { "UpstreamPathTemplate": "/Api_A/{controller}/{action}", "DownstreamPathTemplate": "/api/{controller}/{action}", "UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ], "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 5001 } ], "RateLimitOptions": { "ClientWhitelist": [ "127.0.0.1" ], "EnableRateLimiting": true, "Period": "1m", "PeriodTimespan": 30, "Limit": 5 }, "FileCacheOptions": { "TtlSeconds": 5, "Region": "time" }, "UpstreamHeaderTransform": { "demo": "a,b" }, "DownstreamHeaderTransform": { "demo": "xxxxxxx", "Location": "{DownstreamBaseUrl},{BaseUrl}" }, //受權信息 "AuthenticationOptions": { "AuthenticationProviderKey": "Api_A", "AllowedScopes": [] } }, { "UpstreamPathTemplate": "/Api_B/{controller}/{action}", "DownstreamPathTemplate": "/api/{controller}/{action}", "UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ], "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 5002 } ], //受權信息 "AuthenticationOptions": { "AuthenticationProviderKey": "Api_B", "AllowedScopes": [] } } ], "QoSOptions": { "ExceptionsAllowedBeforeBreaking": 3, "DurationOfBreak": 20, "TimeoutValue": 5000 }, "GlobalConfiguration": { "RateLimitOptions": { "DisableRateLimitHeaders": false, "QuotaExceededMessage": "接口限流!", "HttpStatusCode": 200, "ClientIdHeader": "ClientId" } } }
Ocelot會去檢查ReRoutes是否配置了AuthenticationOptions節點。若是有會根據配置的認證方案進行身份認證。若是沒有則不進行身份認證。
AuthenticationProviderKey 是剛纔註冊的認證方案。
AllowedScopes 是 AllowedScopes中配置的受權訪問範圍。
咱們爲api_a和api_b分別註冊了認證方案。若是咱們不申請token是會401沒有權限訪問。
咱們經過identityServer申請一個的token,並用它訪問api_a和api_b。
能夠看到咱們申請的token是能夠訪問api_a的,可是不能訪問api_b,由於client_a這個客戶端只有訪問api_a的權利。若是想訪問api_b使用client_b申請token就能夠啦。
簡單爲Ocelot集成了IdentityServer,但願對你們有參考價值。若是文中有錯誤請聯繫我更改。