🔒 Implement comprehensive security and DDoS protection
### Security Features: - **Rate Limiting**: Redis-based IP tracking with configurable limits - General: 100 requests/minute (5min block) - Upload: 10 requests/5min (10min block) - Auth: 20 requests/15min (30min block) - **Request Validation**: Path length, header count, suspicious patterns - **Attack Detection**: Admin paths, script injections, bot patterns - **Enhanced JWT**: Format validation, length checks, character filtering - **IP Tracking**: X-Forwarded-For and X-Real-IP support ### Security Headers: - X-Content-Type-Options: nosniff - X-Frame-Options: DENY - X-XSS-Protection: 1; mode=block - Content-Security-Policy with strict rules - Strict-Transport-Security with includeSubDomains ### CORS Hardening: - Limited to specific domains: discours.io, new.discours.io - Restricted methods: GET, POST, OPTIONS only - Essential headers only ### Infrastructure: - Security middleware for all requests - Local cache + Redis for performance - Comprehensive logging and monitoring - Progressive blocking for repeat offenders ### Documentation: - Complete security guide (docs/security.md) - Configuration examples - Incident response procedures - Monitoring recommendations Version bump to 0.6.0 for major security enhancement.
This commit is contained in:
@@ -3,10 +3,11 @@ use actix_web::{HttpRequest, HttpResponse, Result, web};
|
||||
use log::{error, info, warn};
|
||||
|
||||
use crate::app_state::AppState;
|
||||
use crate::auth::{extract_user_id_from_token, user_added_file, validate_token};
|
||||
use crate::auth::{extract_user_id_from_token, user_added_file};
|
||||
use crate::handlers::MAX_USER_QUOTA_BYTES;
|
||||
use crate::lookup::store_file_info;
|
||||
use crate::s3_utils::{self, generate_key_with_extension, upload_to_s3};
|
||||
use super::common::extract_and_validate_token;
|
||||
use futures::TryStreamExt;
|
||||
// use crate::thumbnail::convert_heic_to_jpeg;
|
||||
|
||||
@@ -19,28 +20,8 @@ pub async fn upload_handler(
|
||||
mut payload: Multipart,
|
||||
state: web::Data<AppState>,
|
||||
) -> Result<HttpResponse, actix_web::Error> {
|
||||
// Получаем токен из заголовка авторизации
|
||||
let token = req
|
||||
.headers()
|
||||
.get("Authorization")
|
||||
.and_then(|header_value| header_value.to_str().ok());
|
||||
|
||||
if token.is_none() {
|
||||
warn!("Upload attempt without authorization token");
|
||||
return Err(actix_web::error::ErrorUnauthorized(
|
||||
"Authorization token required",
|
||||
));
|
||||
}
|
||||
|
||||
let token = token.unwrap();
|
||||
|
||||
// Сначала валидируем токен
|
||||
if !validate_token(token).unwrap_or(false) {
|
||||
warn!("Token validation failed");
|
||||
return Err(actix_web::error::ErrorUnauthorized(
|
||||
"Invalid or expired token",
|
||||
));
|
||||
}
|
||||
// Извлекаем и валидируем токен
|
||||
let token = extract_and_validate_token(&req)?;
|
||||
|
||||
// Затем извлекаем user_id
|
||||
let user_id = extract_user_id_from_token(token).map_err(|e| {
|
||||
|
||||
Reference in New Issue
Block a user