feat: add JWT authentication to gateway
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
parent
0cbb5a2c0e
commit
2a4a06ddb8
@ -1,3 +1,4 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using YarpGateway.Data;
|
||||
@ -9,6 +10,7 @@ namespace YarpGateway.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/gateway")]
|
||||
[Authorize] // 要求所有管理 API 都需要认证
|
||||
public class GatewayConfigController : ControllerBase
|
||||
{
|
||||
private readonly IDbContextFactory<GatewayDbContext> _dbContextFactory;
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using YarpGateway.Data;
|
||||
@ -7,6 +8,7 @@ namespace YarpGateway.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/gateway/pending-services")]
|
||||
[Authorize] // 要求所有管理 API 都需要认证
|
||||
public class PendingServicesController : ControllerBase
|
||||
{
|
||||
private readonly IDbContextFactory<GatewayDbContext> _dbContextFactory;
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Serilog;
|
||||
@ -23,10 +24,48 @@ builder.Host.UseSerilog(
|
||||
.Enrich.FromLogContext()
|
||||
);
|
||||
|
||||
// 配置 JWT
|
||||
builder.Services.Configure<JwtConfig>(builder.Configuration.GetSection("Jwt"));
|
||||
builder.Services.Configure<RedisConfig>(builder.Configuration.GetSection("Redis"));
|
||||
builder.Services.AddSingleton(sp => sp.GetRequiredService<IOptions<RedisConfig>>().Value);
|
||||
|
||||
// 添加 JWT 认证
|
||||
var jwtConfig = builder.Configuration.GetSection("Jwt").Get<JwtConfig>();
|
||||
if (jwtConfig != null && !string.IsNullOrEmpty(jwtConfig.Authority))
|
||||
{
|
||||
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
.AddJwtBearer(options =>
|
||||
{
|
||||
options.Authority = jwtConfig.Authority;
|
||||
options.Audience = jwtConfig.Audience;
|
||||
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
|
||||
{
|
||||
ValidateIssuer = jwtConfig.ValidateIssuer,
|
||||
ValidateAudience = jwtConfig.ValidateAudience,
|
||||
ValidateLifetime = true,
|
||||
ValidateIssuerSigningKey = true,
|
||||
ClockSkew = TimeSpan.Zero
|
||||
};
|
||||
|
||||
options.Events = new JwtBearerEvents
|
||||
{
|
||||
OnAuthenticationFailed = context =>
|
||||
{
|
||||
Log.Warning("JWT authentication failed: {Error}", context.Exception?.Message);
|
||||
return Task.CompletedTask;
|
||||
},
|
||||
OnTokenValidated = context =>
|
||||
{
|
||||
Log.Information("JWT token validated for user: {User}",
|
||||
context.Principal?.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value ?? "unknown");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
builder.Services.AddAuthorization();
|
||||
}
|
||||
|
||||
builder.Services.AddDbContextFactory<GatewayDbContext>(options =>
|
||||
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"))
|
||||
);
|
||||
@ -78,6 +117,7 @@ builder.Services.AddServiceDiscovery();
|
||||
|
||||
builder.Services.AddHostedService<KubernetesPendingSyncService>();
|
||||
|
||||
// CORS 配置 - 修复 AllowAnyOrigin 与 AllowCredentials 不兼容问题
|
||||
var corsSettings = builder.Configuration.GetSection("Cors");
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
@ -88,16 +128,18 @@ builder.Services.AddCors(options =>
|
||||
{
|
||||
if (allowAnyOrigin)
|
||||
{
|
||||
policy.AllowAnyOrigin();
|
||||
// AllowAnyOrigin 与 AllowCredentials 不兼容
|
||||
policy.AllowAnyOrigin()
|
||||
.AllowAnyHeader()
|
||||
.AllowAnyMethod();
|
||||
}
|
||||
else
|
||||
{
|
||||
policy.WithOrigins(allowedOrigins);
|
||||
policy.WithOrigins(allowedOrigins)
|
||||
.AllowAnyHeader()
|
||||
.AllowAnyMethod()
|
||||
.AllowCredentials();
|
||||
}
|
||||
|
||||
policy.AllowAnyHeader()
|
||||
.AllowAnyMethod()
|
||||
.AllowCredentials();
|
||||
});
|
||||
});
|
||||
|
||||
@ -109,6 +151,14 @@ builder.Services.AddReverseProxy();
|
||||
var app = builder.Build();
|
||||
|
||||
app.UseCors("AllowFrontend");
|
||||
|
||||
// 添加认证和授权中间件(必须在自定义中间件之前)
|
||||
if (jwtConfig != null && !string.IsNullOrEmpty(jwtConfig.Authority))
|
||||
{
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
}
|
||||
|
||||
app.UseMiddleware<JwtTransformMiddleware>();
|
||||
app.UseMiddleware<TenantRoutingMiddleware>();
|
||||
|
||||
@ -131,4 +181,4 @@ catch (Exception ex)
|
||||
finally
|
||||
{
|
||||
Log.CloseAndFlush();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user