Django如何限制首次登录用户绕过强制改密流程?
全局中间件解决首次登录强制改密的绕过问题
问题背景
新用户通过管理面板或应用创建后,首次登录会被引导至密码修改页面,但存在用户篡改URL直接跳转到首页的漏洞。由于项目包含多个子应用,不想逐个视图添加装饰器,需要全局生效的校验方案。
实现方案:自定义全局中间件
通过Django的全局中间件,对所有已登录且未完成首次改密的用户进行拦截,强制跳转至改密页面,无需修改各个子应用的视图。
1. 编写中间件类
在项目的authentication应用下创建middleware.py文件(如果没有则新建),添加以下代码:
from django.shortcuts import redirect from django.urls import reverse class ForcePasswordChangeMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): # 定义无需拦截的路径:登录页、改密页、admin后台、静态文件 exempt_paths = [ reverse('login'), reverse('user_password_change'), '/admin/', ] # 跳过静态文件请求,避免影响页面资源加载 if request.path.startswith('/static/'): return self.get_response(request) # 仅对已登录且需要首次改密的用户生效 if request.user.is_authenticated: if request.user.is_1st_login == 'Y' and request.path not in exempt_paths: return redirect('user_password_change') # 处理请求并返回响应 response = self.get_response(request) return response
2. 注册中间件
在项目根目录的settings.py中,找到MIDDLEWARE列表,将自定义中间件添加到AuthenticationMiddleware之后(确保能正确获取登录用户信息):
MIDDLEWARE = [ # ... 其他系统中间件 'django.contrib.auth.middleware.AuthenticationMiddleware', # 加入自定义中间件 'authentication.middleware.ForcePasswordChangeMiddleware', # ... 其他中间件 ]
3. 完善改密视图的收尾逻辑
确保用户完成密码修改后,将is_1st_login字段更新为'N',示例代码:
def user_password_change(request): if request.method == "POST": # 此处添加密码修改的表单验证与更新逻辑 form = PasswordChangeForm(request.user, request.POST) if form.is_valid(): user = form.save() # 更新首次登录标记 user.is_1st_login = 'N' user.save() return redirect("/") # 处理表单错误... else: form = PasswordChangeForm(request.user) return render(request, "account/password_change.html", {"form": form})
注意事项
- 避免循环重定向:必须将登录页和改密页加入豁免路径,否则用户会被无限重定向
- 中间件顺序:必须放在
AuthenticationMiddleware之后,否则无法获取request.user的认证信息 - 特殊路径豁免:如果有其他无需拦截的页面(比如公共页面),可以添加到
exempt_paths列表中
内容的提问来源于stack exchange,提问作者Sandeep
相关产品推荐
相关产品推荐

