You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何禁止用户直接通过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')

原有方案失效原因

  1. HTTP_REFERER不可靠:浏览器可能禁用referer发送,或者请求中的referer可能被篡改、缺失,依赖它做验证稳定性差。
  2. 对比逻辑错误: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 04:02:39