Browse Source

feat(open-api): api signature is passed from the request header

pull/1034/head
colin 1 year ago
parent
commit
365ca04833
  1. 27
      aspnet-core/framework/open-api/LINGYUN.Abp.OpenApi.Authorization/LINGYUN/Abp/OpenApi/Authorization/OpenApiAuthorizationService.cs
  2. 8
      aspnet-core/framework/open-api/LINGYUN.Abp.OpenApi/LINGYUN/Abp/OpenApi/AbpOpenApiConsts.cs
  3. 7
      gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.OpenApi.Gateway/GobalUsings.cs
  4. 2
      gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.OpenApi.Gateway/LINGYUN.MicroService.OpenApi.Gateway.csproj
  5. 8
      gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.OpenApi.Gateway/OpenApiGatewayModule.cs
  6. 91
      gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.OpenApi.Gateway/Program.cs
  7. 4
      gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.OpenApi.Gateway/Properties/launchSettings.json
  8. 2
      gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.OpenApi.Gateway/appsettings.Development.json
  9. 433
      gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.OpenApi.Gateway/yarp.json

27
aspnet-core/framework/open-api/LINGYUN.Abp.OpenApi.Authorization/LINGYUN/Abp/OpenApi/Authorization/OpenApiAuthorizationService.cs

@ -84,18 +84,18 @@ namespace LINGYUN.Abp.OpenApi.Authorization
protected async virtual Task<bool> ValidatAppDescriptor(HttpContext httpContext)
{
httpContext.Request.Headers.TryGetValue(AbpOpenApiConsts.AppKeyFieldName, out var appKey);
httpContext.Request.Headers.TryGetValue(AbpOpenApiConsts.SignatureFieldName, out var sign);
httpContext.Request.Headers.TryGetValue(AbpOpenApiConsts.NonceFieldName, out var nonce);
httpContext.Request.Headers.TryGetValue(AbpOpenApiConsts.TimeStampFieldName, out var timeStampString);
httpContext.Request.Headers.TryGetValue(AbpOpenApiConsts.HEADER_APP_KEY, out var appKey);
httpContext.Request.Headers.TryGetValue(AbpOpenApiConsts.HEADER_SIGNATURE, out var sign);
httpContext.Request.Headers.TryGetValue(AbpOpenApiConsts.HEADER_NONCE, out var nonce);
httpContext.Request.Headers.TryGetValue(AbpOpenApiConsts.HEADER_TIMESTAMP, out var timeStampString);
if (StringValues.IsNullOrEmpty(appKey))
{
var exception = new BusinessException(
AbpOpenApiConsts.InvalidAccessWithAppKeyNotFound,
$"{AbpOpenApiConsts.AppKeyFieldName} Not Found",
$"{AbpOpenApiConsts.AppKeyFieldName} Not Found");
$"{AbpOpenApiConsts.HEADER_APP_KEY} Not Found",
$"{AbpOpenApiConsts.HEADER_APP_KEY} Not Found");
await Unauthorized(httpContext, exception);
return false;
}
@ -104,8 +104,8 @@ namespace LINGYUN.Abp.OpenApi.Authorization
{
var exception = new BusinessException(
AbpOpenApiConsts.InvalidAccessWithNonceNotFound,
$"{AbpOpenApiConsts.NonceFieldName} Not Found",
$"{AbpOpenApiConsts.NonceFieldName} Not Found");
$"{AbpOpenApiConsts.HEADER_NONCE} Not Found",
$"{AbpOpenApiConsts.HEADER_NONCE} Not Found");
await Unauthorized(httpContext, exception);
return false;
@ -115,8 +115,8 @@ namespace LINGYUN.Abp.OpenApi.Authorization
{
var exception = new BusinessException(
AbpOpenApiConsts.InvalidAccessWithSignNotFound,
$"{AbpOpenApiConsts.SignatureFieldName} Not Found",
$"{AbpOpenApiConsts.SignatureFieldName} Not Found");
$"{AbpOpenApiConsts.HEADER_SIGNATURE} Not Found",
$"{AbpOpenApiConsts.HEADER_SIGNATURE} Not Found");
await Unauthorized(httpContext, exception);
return false;
@ -126,8 +126,8 @@ namespace LINGYUN.Abp.OpenApi.Authorization
{
var exception = new BusinessException(
AbpOpenApiConsts.InvalidAccessWithTimestampNotFound,
$"{AbpOpenApiConsts.TimeStampFieldName} Not Found",
$"{AbpOpenApiConsts.TimeStampFieldName} Not Found");
$"{AbpOpenApiConsts.HEADER_TIMESTAMP} Not Found",
$"{AbpOpenApiConsts.HEADER_TIMESTAMP} Not Found");
await Unauthorized(httpContext, exception);
return false;
@ -264,7 +264,8 @@ namespace LINGYUN.Abp.OpenApi.Authorization
private static string CalculationSignature(string url, IDictionary<string, string> queryDictionary)
{
var queryString = BuildQuery(queryDictionary);
var encodeUrl = UrlEncode(string.Concat(url, "?", queryString));
// %20 替换 +
var encodeUrl = UrlEncode(string.Concat(url, "?", queryString)).Replace("+", "%20");
return encodeUrl.ToMd5();
}

8
aspnet-core/framework/open-api/LINGYUN.Abp.OpenApi/LINGYUN/Abp/OpenApi/AbpOpenApiConsts.cs

@ -4,10 +4,10 @@ public static class AbpOpenApiConsts
{
public const string SecurityChecking = "_AbpOpenApiSecurityChecking";
public const string AppKeyFieldName = "X-API-APPKEY";
public const string SignatureFieldName = "X-API-SIGN";
public const string NonceFieldName = "X-API-NONCE";
public const string TimeStampFieldName = "X-API-TIMESTAMP";
public const string HEADER_APP_KEY = "X-API-APPKEY";
public const string HEADER_SIGNATURE = "X-API-SIGN";
public const string HEADER_NONCE = "X-API-NONCE";
public const string HEADER_TIMESTAMP = "X-API-TIMESTAMP";
public const string KeyPrefix = "AbpOpenApi";
/// <summary>

7
gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.OpenApi.Gateway/GobalUsings.cs

@ -0,0 +1,7 @@
global using LINGYUN.MicroService.OpenApi.Gateway;
global using Microsoft.AspNetCore.Builder;
global using Microsoft.AspNetCore.Hosting;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Hosting;
global using Serilog;
global using System;

2
gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.OpenApi.Gateway/LINGYUN.MicroService.OpenApi.Gateway.csproj

@ -4,6 +4,8 @@
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>LINGYUN.MicroService.Internal.Gateway</RootNamespace>
<Language>latest</Language>
<ImplicitUsings >enable</ImplicitUsings >
</PropertyGroup>
<ItemGroup>

8
gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.OpenApi.Gateway/OpenApiGatewayModule.cs

@ -5,20 +5,12 @@ using LINGYUN.Abp.Serilog.Enrichers.Application;
using LINGYUN.Abp.Serilog.Enrichers.UniqueId;
using LINGYUN.Abp.Wrapper;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.WebSockets;
using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.ApiExploring;

91
gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.OpenApi.Gateway/Program.cs

@ -1,59 +1,42 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using System;
using System.Threading.Tasks;
namespace LINGYUN.MicroService.OpenApi.Gateway;
public class Program
try
{
public static async Task<int> Main(string[] args)
{
try
Log.Information("Starting OpenApi ApiGateway.");
var builder = WebApplication.CreateBuilder(args);
builder.Host.AddAppSettingsSecretsJson()
.UseAutofac()
.AddYarpJson()
.ConfigureAppConfiguration((context, config) =>
{
Log.Information("Starting OpenApi ApiGateway.");
var builder = WebApplication.CreateBuilder(args);
builder.Host.AddAppSettingsSecretsJson()
.UseAutofac()
.AddYarpJson()
.ConfigureAppConfiguration((context, config) =>
{
var configuration = config.Build();
var agileConfigEnabled = configuration["AgileConfig:IsEnabled"];
if (agileConfigEnabled.IsNullOrEmpty() || bool.Parse(agileConfigEnabled))
{
config.AddAgileConfig(new AgileConfig.Client.ConfigClient(configuration));
}
})
.UseSerilog((context, provider, config) =>
{
config.ReadFrom.Configuration(context.Configuration);
});
await builder.AddApplicationAsync<OpenApiGatewayModule>(options =>
var configuration = config.Build();
var agileConfigEnabled = configuration["AgileConfig:IsEnabled"];
if (agileConfigEnabled.IsNullOrEmpty() || bool.Parse(agileConfigEnabled))
{
OpenApiGatewayModule.ApplicationName = Environment.GetEnvironmentVariable("APPLICATION_NAME")
?? OpenApiGatewayModule.ApplicationName;
options.ApplicationName = OpenApiGatewayModule.ApplicationName;
});
var app = builder.Build();
await app.InitializeApplicationAsync();
await app.RunAsync();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Starting OpenApi ApiGateway terminated unexpectedly!");
return 1;
}
finally
config.AddAgileConfig(new AgileConfig.Client.ConfigClient(configuration));
}
})
.UseSerilog((context, provider, config) =>
{
Log.CloseAndFlush();
}
}
config.ReadFrom.Configuration(context.Configuration);
});
await builder.AddApplicationAsync<OpenApiGatewayModule>(options =>
{
OpenApiGatewayModule.ApplicationName = Environment.GetEnvironmentVariable("APPLICATION_NAME")
?? OpenApiGatewayModule.ApplicationName;
options.ApplicationName = OpenApiGatewayModule.ApplicationName;
});
var app = builder.Build();
await app.InitializeApplicationAsync();
await app.RunAsync();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Starting OpenApi ApiGateway terminated unexpectedly!");
return 1;
}
finally
{
Log.CloseAndFlush();
}

4
gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.OpenApi.Gateway/Properties/launchSettings.json

@ -5,9 +5,9 @@
"launchBrowser": false,
"dotnetRunMessages": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
"ASPNETCORE_ENVIRONMENT": "Production"
},
"applicationUrl": "http://localhost:30000"
"applicationUrl": "http://0.0.0.0:30000"
}
}
}

2
gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.OpenApi.Gateway/appsettings.Development.json

@ -9,7 +9,7 @@
"tag": "BackendAdmin"
},
"App": {
"CorsOrigins": "http://127.0.0.1:3100",
"CorsOrigins": "http://127.0.0.1:3100,http://localhost:9010",
"ShowPii": true
},
"ConnectionStrings": {

433
gateways/internal/LINGYUN.MicroService.Internal.ApiGateway/src/LINGYUN.MicroService.OpenApi.Gateway/yarp.json

@ -1,434 +1,3 @@
{
"ReverseProxy": {
"Routes": {
"abp-route": {
"ClusterId": "admin-api-cluster",
"Match": {
"Path": "/api/abp/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"auth-server-route": {
"ClusterId": "auth-server-cluster",
"Match": {
"Path": "/connect/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"account-route": {
"ClusterId": "auth-server-api-cluster",
"Match": {
"Path": "/api/account/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"identity-route": {
"ClusterId": "auth-server-api-cluster",
"Match": {
"Path": "/api/identity/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"identity-server-route": {
"ClusterId": "auth-server-api-cluster",
"Match": {
"Path": "/api/identity-server/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"cache-management-route": {
"ClusterId": "admin-api-cluster",
"Match": {
"Path": "/api/caching-management/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"saas-route": {
"ClusterId": "admin-api-cluster",
"Match": {
"Path": "/api/saas/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"auditing-route": {
"ClusterId": "admin-api-cluster",
"Match": {
"Path": "/api/auditing/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"data-protected-route": {
"ClusterId": "admin-api-cluster",
"Match": {
"Path": "/api/data-protection-management/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"text-template-route": {
"ClusterId": "admin-api-cluster",
"Match": {
"Path": "/api/text-templating/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"feature-management-route": {
"ClusterId": "admin-api-cluster",
"Match": {
"Path": "/api/feature-management/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"permission-management-route": {
"ClusterId": "admin-api-cluster",
"Match": {
"Path": "/api/permission-management/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"setting-management-route": {
"ClusterId": "admin-api-cluster",
"Match": {
"Path": "/api/setting-management/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"localization-management-route": {
"ClusterId": "localization-api-cluster",
"Match": {
"Path": "/api/localization/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"im-route": {
"ClusterId": "messages-api-cluster",
"Match": {
"Path": "/api/im/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"notifications-route": {
"ClusterId": "messages-api-cluster",
"Match": {
"Path": "/api/notifications/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"signalr-route": {
"ClusterId": "messages-api-cluster",
"Match": {
"Path": "/signalr-hubs/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
},
{
"RequestHeadersCopy": true
},
{
"ResponseHeadersCopy": true
}
]
},
"webhooks-management-route": {
"ClusterId": "webhooks-api-cluster",
"Match": {
"Path": "/api/webhooks/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"task-management-route": {
"ClusterId": "tasks-api-cluster",
"Match": {
"Path": "/api/task-management/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"platform-route": {
"ClusterId": "platform-api-cluster",
"Match": {
"Path": "/api/platform/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"oss-route": {
"ClusterId": "platform-api-cluster",
"Match": {
"Path": "/api/oss-management/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
},
"files-route": {
"ClusterId": "platform-api-cluster",
"Match": {
"Path": "/api/files/{**everything}"
},
"Transforms": [
{
"HeaderPrefix": "X-Forwarded-",
"X-Forwarded": "Append"
},
{
"ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat"
}
]
}
},
"Clusters": {
"auth-server-cluster": {
"Destinations": {
"destination1": {
"Address": "http://auth-server:44385",
"Metadata": {
"SwaggerEndpoint": "http://127.0.0.1:44385"
}
}
}
},
"auth-server-api-cluster": {
"Destinations": {
"destination1": {
"Address": "http://auth-server-api:30015",
"Metadata": {
"SwaggerEndpoint": "http://127.0.0.1:30015"
}
}
}
},
"admin-api-cluster": {
"Destinations": {
"destination1": {
"Address": "http://admin-api:30010",
"Metadata": {
"SwaggerEndpoint": "http://127.0.0.1:30010"
}
}
}
},
"localization-api-cluster": {
"Destinations": {
"destination1": {
"Address": "http://localization-api:30030",
"Metadata": {
"SwaggerEndpoint": "http://127.0.0.1:30030"
}
}
}
},
"messages-api-cluster": {
"Destinations": {
"destination1": {
"Address": "http://messages-api:30020",
"Metadata": {
"SwaggerEndpoint": "http://127.0.0.1:30020"
}
}
}
},
"webhooks-api-cluster": {
"Destinations": {
"destination1": {
"Address": "http://webhooks-api:30045",
"Metadata": {
"SwaggerEndpoint": "http://127.0.0.1:30045"
}
}
}
},
"tasks-api-cluster": {
"Destinations": {
"destination1": {
"Address": "http://tasks-api:30040",
"Metadata": {
"SwaggerEndpoint": "http://127.0.0.1:30040"
}
}
}
},
"platform-api-cluster": {
"Destinations": {
"destination1": {
"Address": "http://platform-api:30025",
"Metadata": {
"SwaggerEndpoint": "http://127.0.0.1:30025"
}
}
}
},
"workflow-api-cluster": {
"Destinations": {
"destination1": {
"Address": "http://workflow-api:30050",
"Metadata": {
"SwaggerEndpoint": "http://127.0.0.1:30050"
}
}
}
}
}
}
"ReverseProxy": {}
}
Loading…
Cancel
Save