mirror of
https://github.com/239573049/FastGateway.git
synced 2026-10-29 14:09:41 +08:00
@@ -19,7 +19,22 @@ public sealed class RouteEntity : Entity
|
||||
/// 绑定集群Id可空
|
||||
/// </summary>
|
||||
public string? ClusterId { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 授权策略
|
||||
/// </summary>
|
||||
public string? AuthorizationPolicy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 认证中心否需要https
|
||||
/// </summary>
|
||||
public bool? RequireHttpsMetadata { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 授权认证中心地址
|
||||
/// </summary>
|
||||
public string? AuthorizationPolicyAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求Body最大长度
|
||||
/// </summary>
|
||||
|
||||
@@ -12,15 +12,17 @@ public static class JwtServiceCollectionExtension
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <param name="options">JWT授权的配置项</param>
|
||||
public static IServiceCollection AddJwtBearerAuthentication(this IServiceCollection services)
|
||||
/// <param name="policies">路由信息</param>
|
||||
public static IServiceCollection AddJwtBearerAuthentication(this IServiceCollection services, List<RouteEntity>? policies = null)
|
||||
{
|
||||
//使用应用密钥得到一个加密密钥字节数组
|
||||
services.AddAuthentication(x =>
|
||||
{
|
||||
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
})
|
||||
.AddCookie(cfg => cfg.SlidingExpiration = true)
|
||||
var authenticationBuilder = services.AddAuthentication(x =>
|
||||
{
|
||||
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
});
|
||||
|
||||
authenticationBuilder.AddCookie(cfg => cfg.SlidingExpiration = true)
|
||||
.AddJwtBearer(x =>
|
||||
{
|
||||
x.RequireHttpsMetadata = true;
|
||||
@@ -34,6 +36,31 @@ public static class JwtServiceCollectionExtension
|
||||
};
|
||||
});
|
||||
|
||||
// 添加认证信息
|
||||
if (policies != null)
|
||||
{
|
||||
foreach (var policy in policies)
|
||||
{
|
||||
authenticationBuilder.AddJwtBearer(policy.AuthorizationPolicy!, options =>
|
||||
{
|
||||
options.Authority = policy.AuthorizationPolicyAddress;
|
||||
options.RequireHttpsMetadata = policy.RequireHttpsMetadata ?? true;
|
||||
options.Audience = policy.AuthorizationPolicy!;
|
||||
});
|
||||
}
|
||||
}
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用自定义授权中间件
|
||||
/// </summary>
|
||||
/// <param name="app">应用程序生成器接口</param>
|
||||
/// <returns>应用程序生成器接口</returns>
|
||||
|
||||
public static IApplicationBuilder UseCustomAuthentication(this IApplicationBuilder app)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(app);
|
||||
return app.UseMiddleware<CustomAuthenticationMiddleware>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Yarp.ReverseProxy.Model;
|
||||
|
||||
namespace Gateway.Middlewares
|
||||
{
|
||||
/// <summary>
|
||||
/// 自定义授权中间件
|
||||
/// </summary>
|
||||
public class CustomAuthenticationMiddleware
|
||||
{
|
||||
/// <summary>
|
||||
/// 请求委托
|
||||
/// </summary>
|
||||
private readonly RequestDelegate _next;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="AuthenticationMiddleware"/>.
|
||||
/// </summary>
|
||||
/// <param name="next">The next item in the middleware pipeline.</param>
|
||||
/// <param name="schemes">The <see cref="IAuthenticationSchemeProvider"/>.</param>
|
||||
public CustomAuthenticationMiddleware(RequestDelegate next, IAuthenticationSchemeProvider schemes)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(next);
|
||||
ArgumentNullException.ThrowIfNull(schemes);
|
||||
|
||||
_next = next;
|
||||
Schemes = schemes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="IAuthenticationSchemeProvider"/>.
|
||||
/// </summary>
|
||||
public IAuthenticationSchemeProvider Schemes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the middleware performing authentication.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="HttpContext"/>.</param>
|
||||
public async Task Invoke(HttpContext context)
|
||||
{
|
||||
var endpoint = context.GetEndpoint()
|
||||
?? throw new InvalidOperationException($"Routing Endpoint wasn't set for the current request.");
|
||||
var route = endpoint.Metadata.GetMetadata<RouteModel>();
|
||||
if (route == null)
|
||||
{
|
||||
await _next(context);
|
||||
return;
|
||||
}
|
||||
var scheme = await GetSchemeAsync(route);
|
||||
if (scheme != null)
|
||||
{
|
||||
var result = await context.AuthenticateAsync(scheme);
|
||||
if (result?.Principal != null)
|
||||
{
|
||||
context.User = result.Principal;
|
||||
}
|
||||
}
|
||||
await _next(context);
|
||||
}
|
||||
|
||||
private async Task<string?> GetSchemeAsync(RouteModel route)
|
||||
{
|
||||
var scheme = route.Config.AuthorizationPolicy;
|
||||
if (scheme == null)
|
||||
{
|
||||
var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
|
||||
return defaultAuthenticate?.Name;
|
||||
}
|
||||
return scheme;
|
||||
}
|
||||
}
|
||||
}
|
||||
+32
-18
@@ -1,5 +1,6 @@
|
||||
#region FreeSql类型转换
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Gateway.BackgroundServices;
|
||||
|
||||
Utils.TypeHandlers.TryAdd(typeof(Dictionary<string, string>), new StringJsonHandler<Dictionary<string, string>>());
|
||||
@@ -11,6 +12,19 @@ Utils.TypeHandlers.TryAdd(typeof(string[]), new StringJsonHandler<string[]>());
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
var directory = new DirectoryInfo("/data");
|
||||
if (!directory.Exists)
|
||||
{
|
||||
directory.Create();
|
||||
}
|
||||
|
||||
var freeSql = new FreeSqlBuilder()
|
||||
.UseConnectionString(DataType.Sqlite, builder.Configuration.GetConnectionString("DefaultConnection"))
|
||||
.UseMonitorCommand(cmd => Console.WriteLine($"Sql:{cmd.CommandText}")) //监听SQL语句
|
||||
.UseAutoSyncStructure(true) //自动同步实体结构到数据库,FreeSql不会扫描程序集,只有CRUD时才会生成表。
|
||||
.Build();
|
||||
|
||||
|
||||
builder.Configuration.GetSection(nameof(JwtOptions))
|
||||
.Get<JwtOptions>();
|
||||
|
||||
@@ -40,7 +54,7 @@ builder.WebHost.UseKestrel(options =>
|
||||
builder.WebHost.ConfigureKestrel(kestrel =>
|
||||
{
|
||||
kestrel.Limits.MaxRequestBodySize = null;
|
||||
|
||||
|
||||
kestrel.ListenAnyIP(8081, portOptions =>
|
||||
{
|
||||
portOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
|
||||
@@ -55,15 +69,25 @@ builder.WebHost.ConfigureKestrel(kestrel =>
|
||||
|
||||
#region Jwt
|
||||
|
||||
|
||||
var policies = freeSql.Select<RouteEntity>().Where(a => a.AuthorizationPolicy != null).Distinct().ToList();
|
||||
|
||||
builder.Services
|
||||
.AddAuthorization()
|
||||
.AddJwtBearerAuthentication();
|
||||
.AddAuthorization(options =>
|
||||
{
|
||||
// 添加授权策略
|
||||
foreach (var policy in policies)
|
||||
{
|
||||
options.AddPolicy(policy.AuthorizationPolicy!, policy => policy.RequireAuthenticatedUser());
|
||||
}
|
||||
})
|
||||
.AddJwtBearerAuthentication(policies);
|
||||
|
||||
#endregion
|
||||
|
||||
builder.Services.Configure<KestrelServerOptions>(options =>
|
||||
{
|
||||
options.Limits.MaxRequestBodySize = int.MaxValue;
|
||||
options.Limits.MaxRequestBodySize = int.MaxValue;
|
||||
});
|
||||
|
||||
builder.Services.Configure<FormOptions>(x =>
|
||||
@@ -110,20 +134,7 @@ builder.Services.AddSingleton<NetWorkService>();
|
||||
|
||||
builder.Services.AddSingleton<IContentTypeProvider, FileExtensionContentTypeProvider>();
|
||||
|
||||
builder.Services.AddSingleton<IFreeSql>(_ =>
|
||||
{
|
||||
var directory = new DirectoryInfo("/data");
|
||||
if (!directory.Exists)
|
||||
{
|
||||
directory.Create();
|
||||
}
|
||||
|
||||
return new FreeSqlBuilder()
|
||||
.UseConnectionString(DataType.Sqlite, builder.Configuration.GetConnectionString("DefaultConnection"))
|
||||
.UseMonitorCommand(cmd => Console.WriteLine($"Sql:{cmd.CommandText}")) //监听SQL语句
|
||||
.UseAutoSyncStructure(true) //自动同步实体结构到数据库,FreeSql不会扫描程序集,只有CRUD时才会生成表。
|
||||
.Build();
|
||||
});
|
||||
builder.Services.AddSingleton<IFreeSql>(freeSql);
|
||||
|
||||
// 使用内存加载配置
|
||||
builder.Services.AddReverseProxy()
|
||||
@@ -147,6 +158,9 @@ app.MapCertificate();
|
||||
app.MapSetting();
|
||||
app.MapNetWork();
|
||||
|
||||
// 添加自定义授权
|
||||
app.UseCustomAuthentication();
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ public class GatewayService(
|
||||
RouteId = route.RouteId,
|
||||
ClusterId = route.ClusterId,
|
||||
MaxRequestBodySize = route.MaxRequestBodySize,
|
||||
AuthorizationPolicy = route.AuthorizationPolicy,
|
||||
Match = new RouteMatch()
|
||||
{
|
||||
Path = route.MatchEntities.Path,
|
||||
|
||||
+1928
-1911
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user