diff --git a/src/Controllers/GatewayConfigController.cs b/src/Controllers/GatewayConfigController.cs index 9be8137..339e315 100644 --- a/src/Controllers/GatewayConfigController.cs +++ b/src/Controllers/GatewayConfigController.cs @@ -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 _dbContextFactory; diff --git a/src/Controllers/PendingServicesController.cs b/src/Controllers/PendingServicesController.cs index 4226cf8..dfb937d 100644 --- a/src/Controllers/PendingServicesController.cs +++ b/src/Controllers/PendingServicesController.cs @@ -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 _dbContextFactory; diff --git a/src/Program.cs b/src/Program.cs index 974adfa..315c9fa 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -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(builder.Configuration.GetSection("Jwt")); builder.Services.Configure(builder.Configuration.GetSection("Redis")); builder.Services.AddSingleton(sp => sp.GetRequiredService>().Value); +// 添加 JWT 认证 +var jwtConfig = builder.Configuration.GetSection("Jwt").Get(); +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(options => options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")) ); @@ -78,6 +117,7 @@ builder.Services.AddServiceDiscovery(); builder.Services.AddHostedService(); +// 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(); app.UseMiddleware(); @@ -131,4 +181,4 @@ catch (Exception ex) finally { Log.CloseAndFlush(); -} +} \ No newline at end of file