前言
上一章已經簡單的介紹了ocelot的使用了,但是網關暴露的接口如果什么人都能訪問的話安全性就太低啦。所以我們需要去鑒權和認證。這里我們使用identityServer4給我們的網關來鑒權認證。
創建Identity服務
我們創建一個identity的服務來用於令牌的發放和鑒權。下圖是我的項目結構。
Api_Gatewat端口:5000
Api_A端口:5001
Api_B端口:5002
IdentityServer端口:5003
通過nuget添加IdentityServer4的包,也可以通過程序包管理控制台執行以下命令Install-Package IdentityServer4
。
添加一個Congif文件。
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資源,並且添加兩個客戶端分別去訪問不同資源。
在 Startup
中的 ConfigureServices
中配置IdentityServer服務。
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients());
}
在 Configure
中把IdentityServer放入http管道中。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseIdentityServer();
}
為ocelot集成Identity
通過nuget添加IdentityServer4.AccessTokenValidation的包,也可以通過程序包管理控制台執行以下命令 Install-Package IdentityServer4.AccessTokenValidation
IdentityServer4.AccessTokenValidation - 用於驗證IdentityServer4中的JWT和引用令牌
在 Startup
的 ConfigureServices
中分別注冊兩個認證方案 Configure
中配置IdentityServer服務。
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,希望對大家有參考價值。如果文中有錯誤請聯系我更改。