前言
上一章已经简单的介绍了 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, 希望对大家有参考价值. 如果文中有错误请联系我更改.
来源: https://www.cnblogs.com/linhuiy/p/12060277.html