Django Axes锁定功能异常:锁定后用户仍可凭正确凭证登录
1. 修复中间件顺序问题
你当前将AxesMiddleware放在AuthenticationMiddleware之后,这会导致Django先完成用户认证,再执行Axes的锁定检查——这就是正确凭证能绕过锁定的核心原因。
调整MIDDLEWARE配置,将axes.middleware.AxesMiddleware移至django.contrib.auth.middleware.AuthenticationMiddleware之前:
MIDDLEWARE = [ # ... 其他中间件(如SessionMiddleware) ... 'axes.middleware.AxesMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', # ... 剩余中间件 ... ]
这样Axes会在用户认证前先检查锁定状态,确保锁定期间无论凭证是否正确都无法登录。
2. 适配Django REST Framework
日志中出现rest_framework.exceptions.AuthenticationFailed,说明你使用了DRF。Axes默认不会自动拦截DRF的认证流程,需额外配置:
方案A:使用AxesBackend
将axes.backends.AxesBackend加入认证后端列表,它会包裹现有后端,在认证前检查锁定状态:
AUTHENTICATION_BACKENDS = [ 'axes.backends.AxesBackend', 'django.contrib.auth.backends.ModelBackend', # 或你的自定义认证后端 # ... 其他后端 ... ]
方案B:装饰DRF登录视图
如果使用自定义DRF登录视图,用axes.decorators.axes_dispatch装饰视图以强制Axes检查:
from axes.decorators import axes_dispatch from rest_framework.views import APIView @axes_dispatch class LoginView(APIView): # 你的登录视图逻辑
3. 验证用户名提取逻辑
日志显示"Using parameter credentials to get username with key settings.AXES_USERNAME_FORM_FIELD",如果你的登录请求使用的用户名字段不是默认的username(比如email或user),需设置AXES_USERNAME_FORM_FIELD匹配实际字段名:
AXES_USERNAME_FORM_FIELD = "你的用户名字段名"
这确保Axes能正确识别尝试登录的用户,是基于用户名锁定的关键前提。
4. 确认锁定生效配置
检查以下配置是否符合需求:
AXES_LOCK_OUT_AT_FAILURE = True:已开启,达到失败次数后触发锁定AXES_COOLOFF_TIME = timedelta(hours=1):正确设置1小时锁定时长AXES_RESET_ON_SUCCESS = False:确保成功登录不会重置锁定状态(符合你要的锁定期间禁止登录的需求)AXES_RESET_COOL_OFF_ON_FAILURE_DURING_LOCKOUT = False:锁定期间的额外失败不会延长锁定时长(当前配置正确)
5. 修改后测试
完成上述配置后:
- 重启Django服务器使中间件变更生效
- 连续3次登录失败触发锁定
- 使用正确凭证尝试登录,此时应该被拦截,直到1小时锁定期满
- 查看Axes日志,确认出现"AXES: Blocked login attempt from locked out user ..."类的拦截记录
内容的提问来源于stack exchange,提问作者Daniyal Maroufi

