feat(security): 添加fail2ban集成防止暴力破解登录

- 新增fail2ban过滤器和监狱配置文件
- 修改登录视图记录客户端IP和认证失败日志
- 更新日志配置添加syslog处理器用于fail2ban检测
- 在README中添加fail2ban配置和使用文档
This commit is contained in:
2026-01-28 22:44:36 +08:00
parent f7692a6db6
commit ae95844177
5 changed files with 411 additions and 9 deletions

View File

@@ -10,6 +10,7 @@ from django.contrib.auth.decorators import login_required
from django.contrib import messages
from datetime import timedelta, datetime
import os
import logging
from loguru import logger
# WeasyPrint可用性标记初始为None
@@ -889,30 +890,42 @@ def api_submit_summary(request):
logger.error(f"API: 提交汇总记录失败: {str(e)}")
return JsonResponse({'success': False, 'message': f"提交失败: {str(e)}"}, status=500)
# 获取syslog日志记录器用于fail2ban检测
syslog_logger = logging.getLogger('django.security.login')
# 登录视图
def user_login(request):
"""用户登录"""
if request.user.is_authenticated:
logger.info(f"用户 {request.user.username} 已登录,重定向到首页")
return redirect('index')
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
logger.info(f"用户登录尝试: {username}")
# 获取客户端IP地址
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
client_ip = x_forwarded_for.split(',')[0].strip()
else:
client_ip = request.META.get('REMOTE_ADDR', 'unknown')
logger.info(f"用户登录尝试: {username}, IP: {client_ip}")
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
logger.info(f"用户 {username} 登录成功")
logger.info(f"用户 {username} 登录成功, IP: {client_ip}")
messages.success(request, '登录成功!')
return redirect('index')
else:
logger.warning(f"用户 {username} 登录失败: 用户名或密码错误")
logger.warning(f"用户 {username} 登录失败: 用户名或密码错误, IP: {client_ip}")
# 记录到syslog供fail2ban检测
syslog_logger.warning(f"Authentication failure for username: {username} from IP: {client_ip}")
messages.error(request, '用户名或密码错误,请重新尝试。')
return render(request, 'core/login.html')
# 注销视图