如何禁止用户直接通过URL访问password_reset/done/页面?
解决Django中password_reset/done页面可直接访问的问题
问题背景
我有password_reset/和password_reset/done/两个页面,用户在password_reset/页面填写表单后会被重定向至password_reset/done/页面,但目前用户可直接通过URL访问该done页面,请问该如何解决?
原有URL配置:
path('password_reset/', views.PasswordResetView.as_view(), name='password_reset'), path('password_reset/done/', views.PasswordResetDoneView.as_view(), name='password_reset_done'),
我尝试通过以下自定义视图解决,但未生效:
class CustomPasswordResetDoneView(PasswordResetDoneView): def get(self, request, *args, **kwargs): referer = request.META.get('HTTP_REFERER') if referer != reverse('password_reset'): return HttpResponse(status=404) return render(request, 'registration/password_reset_done.html')
原有方案失效原因
HTTP_REFERER不可靠:浏览器可能禁用referer发送,或者请求中的referer可能被篡改、缺失,依赖它做验证稳定性差。- 对比逻辑错误:
reverse('password_reset')返回的是相对路径(如/password_reset/),而HTTP_REFERER是完整URL(如http://yourdomain.com/password_reset/),两者永远不会相等,导致正常跳转的用户也会被拦截。
正确解决方案:Session标记验证
通过服务端Session记录用户是否完成了密码重置表单提交,只有存在合法标记时才允许访问password_reset/done页面,步骤如下:
1. 自定义PasswordResetView,添加Session标记
from django.contrib.auth.views import PasswordResetView, PasswordResetDoneView from django.shortcuts import redirect class CustomPasswordResetView(PasswordResetView): def form_valid(self, form): # 先执行父类默认逻辑(发送重置邮件等) response = super().form_valid(form) # 设置Session标记,表明用户刚提交了重置请求 self.request.session['password_reset_initiated'] = True return response
2. 自定义PasswordResetDoneView,验证Session标记
class CustomPasswordResetDoneView(PasswordResetDoneView): def get(self, request, *args, **kwargs): # 检查Session中是否存在合法标记 if not request.session.get('password_reset_initiated'): # 无标记时重定向到密码重置页面,也可返回404 return redirect('password_reset') # 访问后立即删除标记,避免用户刷新或再次通过URL直接访问 del request.session['password_reset_initiated'] # 执行父类默认逻辑渲染页面 return super().get(request, *args, **kwargs)
3. 更新URL配置
path('password_reset/', views.CustomPasswordResetView.as_view(), name='password_reset'), path('password_reset/done/', views.CustomPasswordResetDoneView.as_view(), name='password_reset_done'),
方案优势
- 可靠性高:Session由服务端控制,不会被客户端篡改或轻易丢失。
- 逻辑严谨:访问
done页面后立即删除标记,避免用户重复访问或刷新页面后仍能进入。
内容的提问来源于stack exchange,提问作者Daniil Filippov
相关产品推荐
相关产品推荐

