Feat: Ajustes de seguridad
This commit is contained in:
@@ -78,25 +78,28 @@ builder.Services.AddRateLimiter(options =>
|
||||
|
||||
options.AddPolicy("AuthPolicy", context =>
|
||||
{
|
||||
// Si es localhost, SIN LÍMITES
|
||||
// Si es localhost, SIN LÍMITES (Evita auto-bloqueo en desarrollo)
|
||||
var remoteIp = context.Connection.RemoteIpAddress;
|
||||
if (System.Net.IPAddress.IsLoopback(remoteIp!))
|
||||
if (remoteIp != null && System.Net.IPAddress.IsLoopback(remoteIp))
|
||||
{
|
||||
return RateLimitPartition.GetNoLimiter("loopback_auth");
|
||||
}
|
||||
|
||||
return RateLimitPartition.GetFixedWindowLimiter(
|
||||
partitionKey: remoteIp?.ToString() ?? "unknown",
|
||||
factory: _ => new FixedWindowRateLimiterOptions
|
||||
{
|
||||
AutoReplenishment = true,
|
||||
PermitLimit = 5, // 5 intentos por minuto para IPs externas
|
||||
QueueLimit = 0,
|
||||
Window = TimeSpan.FromMinutes(1)
|
||||
});
|
||||
return RateLimitPartition.GetFixedWindowLimiter("auth_limit", _ => new FixedWindowRateLimiterOptions
|
||||
{
|
||||
PermitLimit = 5,
|
||||
Window = TimeSpan.FromMinutes(1),
|
||||
QueueLimit = 0
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// 🛡️ SEGURIDAD: Evitar que el host se caiga si un servicio de fondo falla
|
||||
builder.Services.Configure<HostOptions>(options =>
|
||||
{
|
||||
options.BackgroundServiceExceptionBehavior = BackgroundServiceExceptionBehavior.Ignore;
|
||||
});
|
||||
|
||||
// DB CONTEXTS (Legacy unificado en eldia)
|
||||
builder.Services.AddDbContext<EldiaDbContext>(options =>
|
||||
options.UseSqlServer(builder.Configuration.GetConnectionString("eldia")));
|
||||
@@ -119,6 +122,7 @@ builder.Services.Configure<MailSettings>(builder.Configuration.GetSection("SmtpS
|
||||
builder.Services.AddScoped<IEmailService, SmtpEmailService>();
|
||||
builder.Services.AddScoped<IImageStorageService, ImageStorageService>();
|
||||
builder.Services.AddHostedService<AdExpirationService>();
|
||||
builder.Services.AddHostedService<TokenCleanupService>();
|
||||
|
||||
// 🔒 JWT AUTH
|
||||
var jwtKey = builder.Configuration["Jwt:Key"] ?? throw new InvalidOperationException("JWT Key Missing");
|
||||
@@ -158,8 +162,10 @@ builder.Services.AddSwaggerGen();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// USAR EL MIDDLEWARE AL PRINCIPIO
|
||||
// Debe ser lo primero para que el RateLimiter y los Logs vean la IP real
|
||||
// Middleware de Manejo Global de Excepciones (Debe ser el primero para atrapar todo)
|
||||
app.UseMiddleware<MotoresArgentinosV2.API.Middleware.ExceptionHandlingMiddleware>();
|
||||
|
||||
// USAR EL MIDDLEWARE DE HEADERS
|
||||
app.UseForwardedHeaders();
|
||||
|
||||
// 🔒 HEADERS DE SEGURIDAD MIDDLEWARE
|
||||
@@ -170,6 +176,9 @@ app.Use(async (context, next) =>
|
||||
context.Response.Headers.Append("Referrer-Policy", "strict-origin-when-cross-origin");
|
||||
context.Response.Headers.Append("X-XSS-Protection", "1; mode=block");
|
||||
|
||||
// Permissions-Policy: Bloquear funcionalidades sensibles del navegador no usadas
|
||||
context.Response.Headers.Append("Permissions-Policy", "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()");
|
||||
|
||||
// CSP adaptada para permitir pagos en Payway y WebSockets de Vite
|
||||
string csp = "default-src 'self'; " +
|
||||
"img-src 'self' data: https: blob:; " +
|
||||
|
||||
Reference in New Issue
Block a user