feat(security): 添加fail2ban集成防止暴力破解登录
- 新增fail2ban过滤器和监狱配置文件 - 修改登录视图记录客户端IP和认证失败日志 - 更新日志配置添加syslog处理器用于fail2ban检测 - 在README中添加fail2ban配置和使用文档
This commit is contained in:
@@ -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')
|
||||
|
||||
# 注销视图
|
||||
|
||||
Reference in New Issue
Block a user