This commit is contained in:
cjd
2025-11-04 21:09:16 +08:00
parent 8260e293c7
commit bb90a020dc
592 changed files with 61749 additions and 27 deletions

View File

@@ -0,0 +1,42 @@
using DouyinApi.Common.HttpContextUser;
using DouyinApi.Model;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;
namespace DouyinApi.Gateway.Controllers
{
[Authorize(AuthenticationSchemes = Permissions.GWName)]
[Route("/gateway/[controller]/[action]")]
public class UserController : ControllerBase
{
private readonly IUser _user;
public UserController(IUser user)
{
_user = user;
}
[HttpGet]
public MessageModel<List<ClaimDto>> MyClaims()
{
return new MessageModel<List<ClaimDto>>()
{
success = true,
response = (_user.GetClaimsIdentity().ToList()).Select(d =>
new ClaimDto
{
Type = d.Type,
Value = d.Value
}
).ToList()
};
}
}
public class ClaimDto
{
public string Type { get; set; }
public string Value { get; set; }
}
}

View File

@@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>..\DouyinApi.Gateway\DouyinApi.Gateway.xml</DocumentationFile>
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Extensions\ApiResponseHandler.cs" />
<Compile Remove="Helper\HeaderDelegatingHandler.cs" />
</ItemGroup>
<ItemGroup>
<None Remove="index.html" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="index.html" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.10" NoWarn="NU1605" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.10" NoWarn="NU1605" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="8.0.10" />
<PackageReference Include="Ocelot" Version="20.0.0" />
<PackageReference Include="Ocelot.Provider.Consul" Version="20.0.0" />
<PackageReference Include="Ocelot.Provider.Polly" Version="20.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DouyinApi.Extensions\DouyinApi.Extensions.csproj" />
<ProjectReference Include="..\DouyinApi.Model\DouyinApi.Model.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,55 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>DouyinApi.Gateway</name>
</assembly>
<members>
<member name="T:DouyinApi.AuthHelper.CustomJwtTokenAuthMiddleware">
<summary>
中间件
原做为自定义授权中间件
先做检查 header token的使用
</summary>
</member>
<member name="P:DouyinApi.AuthHelper.CustomJwtTokenAuthMiddleware.Schemes">
<summary>
验证方案提供对象
</summary>
</member>
<member name="F:DouyinApi.AuthHelper.CustomJwtTokenAuthMiddleware._next">
<summary>
请求上下文
</summary>
</member>
<member name="M:DouyinApi.AuthHelper.CustomJwtTokenAuthMiddleware.Invoke(Microsoft.AspNetCore.Http.HttpContext)">
<summary>
网关授权
</summary>
<param name="httpContext"></param>
<returns></returns>
</member>
<member name="M:DouyinApi.AuthHelper.CustomJwtTokenAuthMiddleware.SendResponse(Microsoft.AspNetCore.Http.HttpContext,System.String,System.Net.HttpStatusCode)">
<summary>
返回相应
</summary>
<param name="context"></param>
<param name="message"></param>
<param name="code"></param>
<returns></returns>
</member>
<member name="M:DouyinApi.AuthHelper.CustomJwtTokenAuthMiddleware.CheckWhiteList(System.String)">
<summary>
判断是否在白名单内,支持通配符 ****
</summary>
<param name="url"></param>
<returns></returns>
</member>
<member name="M:DouyinApi.AdminMvc.Startup.#ctor(Microsoft.Extensions.Configuration.IConfiguration,Microsoft.AspNetCore.Hosting.IWebHostEnvironment)">
┌──────────────────────────────────────────────────────────────┐
│ 描 述:模拟一个网关项目
│ 测 试在网关swagger中查看具体的服务
│ 作 者anson zhang
└──────────────────────────────────────────────────────────────┘
</member>
</members>
</doc>

View File

@@ -0,0 +1,77 @@
using DouyinApi.Model;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DouyinApi.Gateway.Extensions
{
/// <summary>
/// 这里不需要,目前集成的是 DouyinApi.Extensions 下的接口处理器
/// 但是你可以单独在网关中使用这个。
/// </summary>
public class ApiResponseHandler : DelegatingHandler
{
JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings()
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
var contentType = response.Content.Headers.ContentType?.MediaType ?? "";
if (!contentType.Equals("application/json")) return response;
dynamic result = null;
var resultStr = await response.Content.ReadAsStringAsync();
try
{
result = JsonConvert.DeserializeObject<dynamic>(resultStr);
}
catch (Exception)
{
return response;
}
if (result != null && result.code == 500) resultStr = result.msg.ToString();
var apiResponse = new ApiResponse(StatusCode.CODE200).MessageModel;
if (response.StatusCode != HttpStatusCode.OK || result.code == (int)HttpStatusCode.InternalServerError)
{
var exception = new Exception(resultStr);
apiResponse = new ApiResponse(StatusCode.CODE500).MessageModel;
}
else if (result.code == (int)HttpStatusCode.Unauthorized)
{
apiResponse = new ApiResponse(StatusCode.CODE401).MessageModel;
}
else if (result.code == (int)HttpStatusCode.Forbidden)
{
apiResponse = new ApiResponse(StatusCode.CODE403).MessageModel;
}
else
{
}
var statusCode = apiResponse.status == 500 ? HttpStatusCode.InternalServerError
: apiResponse.status == 401 ? HttpStatusCode.Unauthorized
: apiResponse.status == 403 ? HttpStatusCode.Forbidden
: HttpStatusCode.OK;
response.StatusCode = statusCode;
response.Content = new StringContent(JsonConvert.SerializeObject(apiResponse, jsonSerializerSettings), Encoding.UTF8, "application/json");
return response;
}
}
}

View File

@@ -0,0 +1,53 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Headers;
using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
namespace DouyinApi.Gateway.Extensions
{
public class CustomAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
public CustomAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock) : base(options, logger, encoder, clock)
{
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
// 可以查询数据库等操作
// 获取当前用户不能放到token中的私密信息
var userPhone = "15010000000";
var claims = new List<Claim>()
{
new Claim("user-phone", userPhone),
new Claim("gw-sign", "gw")
};
var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, Scheme.Name));
var ticket = new AuthenticationTicket(principal, Scheme.Name);
await Task.CompletedTask;
return AuthenticateResult.Success(ticket);
}
protected virtual string GetTokenStringFromHeader()
{
var token = string.Empty;
string authorization = Request.Headers[HeaderNames.Authorization];
if (!string.IsNullOrEmpty(authorization) && authorization.StartsWith($"Bearer ", StringComparison.OrdinalIgnoreCase))
{
token = authorization["Bearer ".Length..].Trim();
}
return token;
}
}
}

View File

@@ -0,0 +1,34 @@
using DouyinApi.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using Ocelot.Provider.Nacos;
using Ocelot.Provider.Polly;
using System;
using System.Threading.Tasks;
namespace DouyinApi.Gateway.Extensions
{
public static class CustomOcelotSetup
{
public static void AddCustomOcelotSetup(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
services.AddAuthentication_JWTSetup();
services.AddOcelot()
.AddDelegatingHandler<CustomResultHandler>()
//.AddNacosDiscovery()
//.AddConsul()
.AddPolly();
}
public static async Task<IApplicationBuilder> UseCustomOcelotMildd(this IApplicationBuilder app)
{
await app.UseOcelot();
return app;
}
}
}

View File

@@ -0,0 +1,62 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DouyinApi.Gateway.Extensions
{
public class CustomResultHandler : DelegatingHandler
{
JsonSerializerSettings _camelSettings = new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() };
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
var contentType = response.Content.Headers.ContentType?.MediaType ?? "";
if (!contentType.Equals("application/json")) return response;
dynamic result = null;
var resultStr = await response.Content.ReadAsStringAsync();
try
{
Console.WriteLine(resultStr);
result = JsonConvert.DeserializeObject<dynamic>(resultStr);
}
catch (Exception)
{
return response;
}
if (result != null && result.errorCode == 500) resultStr = result.message.ToString();
var exception = new Exception(resultStr);
if (response.StatusCode == HttpStatusCode.InternalServerError || result.errorCode == (int)HttpStatusCode.InternalServerError)
{
var apiResult = new
{
Result = false,
Message = "服务器内部错误",
ErrorCode = (int)HttpStatusCode.InternalServerError,
Data = new
{
exception.Message,
exception.StackTrace
}
};
response.Content = new StringContent(JsonConvert.SerializeObject(apiResult, _camelSettings), Encoding.UTF8, "application/json");
}
else
{
}
return response;
}
}
}

View File

@@ -0,0 +1,81 @@
using DouyinApi.Common;
using DouyinApi.Extensions.Middlewares;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.Filters;
using Swashbuckle.AspNetCore.SwaggerUI;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using static DouyinApi.Extensions.CustomApiVersion;
namespace DouyinApi.Gateway.Extensions
{
public static class CustomSwaggerSetup
{
public static void AddCustomSwaggerSetup(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
var basePath = AppContext.BaseDirectory;
services.AddMvc(option => option.EnableEndpointRouting = false);
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "自定义网关 接口文档",
});
var xmlPath = Path.Combine(basePath, "DouyinApi.Gateway.xml");
c.IncludeXmlComments(xmlPath, true);
c.OperationFilter<AddResponseHeadersFilter>();
c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
c.OperationFilter<SecurityRequirementsOperationFilter>();
c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)\"",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey
});
});
}
public static void UseCustomSwaggerMildd(this IApplicationBuilder app, Func<Stream> streamHtml)
{
if (app == null) throw new ArgumentNullException(nameof(app));
var apis = new List<string> { "blog-svc" };
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint($"/swagger/v1/swagger.json", "gateway");
apis.ForEach(m =>
{
c.SwaggerEndpoint($"/swagger/apiswg/{m}/swagger.json", m);
});
if (streamHtml.Invoke() == null)
{
var msg = "index.html的属性必须设置为嵌入的资源";
throw new Exception(msg);
}
c.IndexStream = streamHtml;
c.RoutePrefix = "";
});
}
}
}

View File

@@ -0,0 +1,187 @@
using System.Net;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Authentication;
using DouyinApi.Common;
using DouyinApi.Common.Caches;
using DouyinApi.Common.Caches.Interface;
using DouyinApi.Common.Helper;
namespace DouyinApi.AuthHelper
{
/// <summary>
/// 中间件
/// 原做为自定义授权中间件
/// 先做检查 header token的使用
/// </summary>
public class CustomJwtTokenAuthMiddleware
{
private readonly ICaching _cache;
/// <summary>
/// 验证方案提供对象
/// </summary>
public IAuthenticationSchemeProvider Schemes { get; set; }
/// <summary>
/// 请求上下文
/// </summary>
private readonly RequestDelegate _next;
public CustomJwtTokenAuthMiddleware(RequestDelegate next, IAuthenticationSchemeProvider schemes, AppSettings appset,ICaching cache)
{
_cache = cache;
_next = next;
Schemes = schemes;
}
/// <summary>
/// 网关授权
/// </summary>
/// <param name="httpContext"></param>
/// <returns></returns>
public async Task Invoke(HttpContext httpContext)
{
var questUrl = httpContext?.Request.Path.Value.ToLower();
if (string.IsNullOrEmpty(questUrl)) return;
//白名单验证
if (CheckWhiteList(questUrl))
{
await _next.Invoke(httpContext);
return;
}
//黑名单验证
if(CheckBlackList(questUrl))
{
return;
}
List<PermissionItem> Permissions= new();
httpContext.Features.Set<IAuthenticationFeature>(new AuthenticationFeature
{
OriginalPath = httpContext.Request.Path,
OriginalPathBase = httpContext.Request.PathBase
});
//判断请求是否拥有凭据,即有没有登录
var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
if (defaultAuthenticate != null)
{
var Authresult = await httpContext.AuthenticateAsync(defaultAuthenticate.Name);
if (Authresult?.Principal != null)
{
httpContext.User = Authresult.Principal;
// 获取当前用户的角色信息
var currentUserRoles = (from item in httpContext.User.Claims
where item.Type == "CofRole"
select item.Value).ToList();
var isMatchRole = false;
var permisssionRoles = Permissions.Where(w => currentUserRoles.Contains(w.Role));
foreach (var item in permisssionRoles)
{
try
{
if (Regex.IsMatch(questUrl, item.Url, RegexOptions.IgnoreCase))
{
isMatchRole = true;
break;
}
}
catch (Exception)
{
// ignored
}
}
//验证权限
if (currentUserRoles.Count <= 0 || !isMatchRole)
{
await httpContext.Cof_SendResponse(HttpStatusCode.ServiceUnavailable, "未授权此资源");
return ;
}
}
else
{
await httpContext.Cof_SendResponse(HttpStatusCode.Unauthorized, "请重新登录");
return ;
}
}
else
{
await httpContext.Cof_SendResponse(HttpStatusCode.Unauthorized, "系统鉴权出错");
return ;
}
await _next.Invoke(httpContext);
}
/// <summary>
/// 返回相应
/// </summary>
/// <param name="context"></param>
/// <param name="message"></param>
/// <param name="code"></param>
/// <returns></returns>
private async Task SendResponse(HttpContext context, string message, HttpStatusCode code)
{
context.Response.StatusCode = (int)code;
context.Response.ContentType = "text/plain";
await context.Response.WriteAsync(message);
}
/// <summary>
/// 判断是否在白名单内,支持通配符 ****
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public bool CheckWhiteList(string url)
{
List<Urlobj> WhiteList = _cache.Cof_GetICaching<List<Urlobj>>("WhiteList", () => AppSettings.app<Urlobj>("WhiteList"), 10);
if (!WhiteList.Cof_CheckAvailable()) return false;
foreach (var Urlitem in WhiteList)
{
if (Urlitem.url.Equals(url, StringComparison.OrdinalIgnoreCase)) return true;
if (Urlitem.url.IndexOf("****") > 0)
{
string UrlitemP = Urlitem.url.Replace("****", "");
if (Regex.IsMatch(url, UrlitemP, RegexOptions.IgnoreCase)) return true;
if (url.Length >= UrlitemP.Length && UrlitemP.ToLower() == url.Substring(0, UrlitemP.Length).ToLower()) return true;
}
}
return false;
}
public bool CheckBlackList(string url)
{
List<Urlobj> BlackList = _cache.Cof_GetICaching<List<Urlobj>>("BlackList", () => AppSettings.app<Urlobj>("BlackList"), 10);
if (!BlackList.Cof_CheckAvailable()) return false;
foreach (var Urlitem in BlackList)
{
if (Urlitem.url.Equals(url, StringComparison.OrdinalIgnoreCase)) return true;
if (Urlitem.url.IndexOf("****") > 0)
{
string UrlitemP = Urlitem.url.Replace("****", "");
if (Regex.IsMatch(url, UrlitemP, RegexOptions.IgnoreCase)) return true;
if (url.Length >= UrlitemP.Length && UrlitemP.ToLower() == url.Substring(0, UrlitemP.Length).ToLower()) return true;
}
}
return false;
}
}
public class Urlobj
{
public string url { get; set; }
}
}

View File

@@ -0,0 +1,35 @@
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ApiGateway.Helper
{
public class HeaderDelegatingHandler : DelegatingHandler
{
private readonly IHttpContextAccessor _httpContextAccessor;
public HeaderDelegatingHandler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
IEnumerable<string> headerValues;
if (request.Headers.TryGetValues("AccessToken", out headerValues))
{
string accessToken = headerValues.First();
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
request.Headers.Remove("AccessToken");
}
return await base.SendAsync(request, cancellationToken);
}
}
}

View File

@@ -0,0 +1,28 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace DouyinApi.AdminMvc
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddJsonFile("appsettings.gw.json", optional: true, reloadOnChange: false)
.AddJsonFile($"appsettings.gw.{hostingContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: false)
.AddJsonFile("ocelot.json", optional: true, reloadOnChange: true)
.AddJsonFile($"ocelot.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>().UseUrls("http://*:9000");
});
}
}

View File

@@ -0,0 +1,12 @@
{
"profiles": {
"DouyinApi.Gateway": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "http://localhost:9000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,80 @@
using DouyinApi.AuthHelper;
using DouyinApi.Common;
using DouyinApi.Common.Caches;
using DouyinApi.Extensions;
using DouyinApi.Gateway.Extensions;
using Microsoft.AspNetCore.Authentication;
using System.Reflection;
using DouyinApi.Common.Caches.Interface;
namespace DouyinApi.AdminMvc
{
public class Startup
{
/**
*┌──────────────────────────────────────────────────────────────┐
*│ 描 述:模拟一个网关项目
*│ 测 试在网关swagger中查看具体的服务
*│ 作 者anson zhang
*└──────────────────────────────────────────────────────────────┘
*/
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(new AppSettings(Configuration));
services.AddAuthentication()
.AddScheme<AuthenticationSchemeOptions, CustomAuthenticationHandler>(Permissions.GWName, _ => { });
services.AddCustomSwaggerSetup();
services.AddControllers();
services.AddHttpContextSetup();
services.AddCorsSetup();
services.AddMemoryCache();
services.AddDistributedMemoryCache();
services.AddSingleton<ICaching, Caching>();
services.AddCustomOcelotSetup();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCustomSwaggerMildd(() => Assembly.GetExecutingAssembly().GetManifestResourceStream("DouyinApi.Gateway.index.html"));
app.UseCors(AppSettings.app(new string[] { "Startup", "Cors", "PolicyName" }));
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseMiddleware<CustomJwtTokenAuthMiddleware>();
app.UseCustomOcelotMildd().Wait();
}
}
}

View File

@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}

View File

@@ -0,0 +1,51 @@
{
"Logging": {
"Debug": {
"LogLevel": {
"Default": "Warning"
}
},
"Console": {
"LogLevel": {
"Default": "Warning",
"Microsoft.Hosting.Lifetime": "Debug"
}
}
},
"AllowedHosts": "*",
"Startup": {
"Cors": {
"PolicyName": "CorsIpAccess",
"EnableAllIPs": false,
"IPs": "http://127.0.0.1:2364,http://localhost:2364"
}
},
"Redis": {
"Enable": false,
"ConnectionString": "127.0.0.1:6379",
"InstanceName": "" //前缀
},
"Audience": {
"Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs",
"SecretFile": "C:\\my-file\\douyinapi.audience.secret.txt",
"Issuer": "DouyinApi",
"Audience": "wr"
},
"WhiteList": [
{ "url": "/" },
{ "url": "/illagal/****" },
{ "url": "/api3/****" },
{ "url": "/baseapi/swagger.json" },
{ "url": "/swagger/v1/swagger.json" },
{ "url": "/swagger/apiswg/blog-svc/swagger.json" }
],
"BlackList": [
{ "url": "/favicon.ico" }
],
"Influxdb": {
"Endpoint": "http://*******:9328",
"uid": "root",
"pwd": "*****",
"dbname": "mndata"
}
}

View File

@@ -0,0 +1,124 @@
<!--1、版本号要与nuget包一致2、id不能为空-->
<script async id="mini-profiler" src="/mini-profiler-resources/includes.min.js?v=4.2.1+b27bea37e9" data-version="4.2.1+b27bea37e9" data-path="/mini-profiler-resources/" data-current-id="144b1192-acd3-4fe2-bbc5-6f1e1c6d53df" data-ids="87a1341b-995d-4d1d-aaba-8f2bfcfc9ca9,144b1192-acd3-4fe2-bbc5-6f1e1c6d53df" data-position="Left" data-scheme="Light" data-authorized="true" data-max-traces="15" data-toggle-shortcut="Alt+P" data-trivial-milliseconds="2.0" data-ignored-duplicate-execute-types="Open,OpenAsync,Close,CloseAsync">
</script>
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--极速模式-->
<meta name="renderer" content="webkit" />
<meta name="force-rendering" content="webkit" />
<title>%(DocumentTitle)</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="./swagger-ui.css">
<link rel="icon" type="image/png" href="./logo/favicon-32x32.png" sizes="32x32" />
<script src="/js/jquery-3.3.1.min.js"></script>
<style>
html {
box-sizing: border-box;
overflow-y: scroll;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
background: #fafafa;
}
.qqgroup {
position: absolute;
top: 67px;
right: 10px;
}
.info {
float: left;
}
.download-contents {
display: none;
}
</style>
%(HeadContent)
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0">
<defs>
<symbol viewBox="0 0 20 20" id="unlocked">
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
</symbol>
<symbol viewBox="0 0 20 20" id="locked">
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z" />
</symbol>
<symbol viewBox="0 0 20 20" id="close">
<path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z" />
</symbol>
<symbol viewBox="0 0 20 20" id="large-arrow">
<path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z" />
</symbol>
<symbol viewBox="0 0 20 20" id="large-arrow-down">
<path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z" />
</symbol>
<symbol viewBox="0 0 24 24" id="jump-to">
<path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z" />
</symbol>
<symbol viewBox="0 0 24 24" id="expand">
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z" />
</symbol>
</defs>
</svg>
<div id="swagger-ui"></div>
<div id="footer" style="text-align: center;margin-bottom: 10px;">
Copyright © 2018-2022 BCVP
<br><span id="poweredby">Powered by .NET 5.0.0 on Docker & CentOS 7</span>
</div>
<!-- Workaround for https://github.com/swagger-api/swagger-editor/issues/1371 -->
<script>
if (window.navigator.userAgent.indexOf("Edge") > -1) {
console.log("Removing native Edge fetch in favor of swagger-ui's polyfill")
window.fetch = undefined;
}
</script>
<script src="./swagger-ui-bundle.js"></script>
<script src="./swagger-ui-standalone-preset.js"></script>
<script>
var int = null;
if (window.location.href.indexOf("docExpansion") < 0)
window.location = window.location.href.replace("index.html", "index.html?docExpansion=none");
window.onload = function () {
var configObject = JSON.parse('%(ConfigObject)');
var oauthConfigObject = JSON.parse('%(OAuthConfigObject)');
// Apply mandatory parameters
configObject.dom_id = "#swagger-ui";
configObject.presets = [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset];
configObject.layout = "StandaloneLayout";
// If oauth2RedirectUrl isn't specified, use the built-in default
if (!configObject.hasOwnProperty("oauth2RedirectUrl"))
configObject.oauth2RedirectUrl = window.location.href.replace("index.html", "oauth2-redirect.html");
// Build a system
const ui = SwaggerUIBundle(configObject);
// Apply OAuth config
ui.initOAuth(oauthConfigObject);
}
</script>
</body>
</html>

View File

@@ -0,0 +1,54 @@
{
"Routes": [
// blog-svc
{
"UpstreamPathTemplate": "/svc/blog/{url}",
"UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ],
"LoadBalancerOptions": {
"Type": "RoundRobin"
},
"DownstreamPathTemplate": "/svc/blog/{url}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 9291
}
],
"AddHeadersToRequest": {
"user-phone": "Claims[user-phone] > value",
"gw-sign": "Claims[gw-sign] > value"
},
"UpstreamHeaderTransform": {
"custom-key": "blog.gateway"
},
"DownstreamHeaderTransform": {
"trace-id": "Trace-Id"
},
"AuthenticationOptions": {
"AuthenticationProviderKey": "GW"
},
"DelegatingHandlers": [
"CustomResultHandler"
]
},
// blog-svc-swagger
{
"UpstreamPathTemplate": "/swagger/apiswg/blog-svc/swagger.json",
"UpstreamHttpMethod": [ "GET" ],
"DownstreamPathTemplate": "/swagger/V2/swagger.json",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 9291
}
],
"LoadBalancer": "RoundRobin"
}
],
"GlobalConfiguration": {
"BaseUrl": "http://localhost:9000"
}
}

View File

@@ -0,0 +1,3 @@
{
}

View File

@@ -0,0 +1,3 @@
{
}

View File

@@ -0,0 +1,3 @@
{
}