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

Django密码重置邮件链接点击失效、复制粘贴可正常使用问题

问题触发原因
  • 核心原因是Gmail、Outlook等邮件服务商的链接安全扫描机制和中转跳转机制共同导致的:
    1. 主流邮件服务默认会将邮件内的链接替换为自身的中转链接,用户点击时先跳转到邮件服务商域名再跳转回你的站点,属于跨站跳转场景
    2. 大部分邮件安全网关/中转服务会主动剥离跳转响应中的Set-Cookie头,防止跨站用户跟踪,导致第一次请求存token时返回的session cookie没有被用户浏览器接收
    3. 少数情况是站点的SESSION_COOKIE_SAMESITE配置为Strict,跨站跳转的请求无法携带session cookie,重定向后新的请求对应全新的空session,自然拿不到之前存储的token
    4. 更低概率的场景是邮件爬虫在用户点击前提前访问了带token的链接,将token存入了爬虫的独立会话,该场景下日志会出现两次相同token的dispatch调用,和你提供的日志特征不符,可以优先排查前三种原因
解决方案

方案1(最稳妥,无兼容性问题)

重写PasswordResetConfirmView,取消跳转逻辑,验证token有效后直接渲染密码重置表单,完全规避session存token的依赖:

from django.contrib.auth.views import PasswordResetConfirmView as BasePasswordResetConfirmView
from django.contrib.auth import views as auth_views

class PasswordResetConfirmView(BasePasswordResetConfirmView):
    def dispatch(self, *args, **kwargs):
        self.validlink = False
        self.user = self.get_user(kwargs['uidb64'])
        if self.user is not None:
            token = kwargs['token']
            # 带有效token的访问直接设置验证通过,不走跳转逻辑
            if token != self.reset_url_token and self.token_generator.check_token(self.user, token):
                self.validlink = True
                return super().dispatch(*args, **kwargs)
            # 保留原set-password路径逻辑,兼容旧访问入口
            elif token == self.reset_url_token:
                session_token = self.request.session.get(auth_views.INTERNAL_RESET_SESSION_TOKEN)
                if self.token_generator.check_token(self.user, session_token):
                    self.validlink = True
                    return super().dispatch(*args, **kwargs)
        # 验证失败走原生失败分支
        return self.render_to_response(self.get_context_data())

替换urls.py中原本的密码重置确认视图即可,该方案唯一缺点是如果用户从重置页面跳转到第三方站点,token可能会通过Referer头泄露,实际风险极低。

方案2(调整cookie配置,适配跨站跳转)

如果不想修改视图逻辑,可以调整settings.py中的session cookie配置:

# 允许Session Cookie跨站携带,必须同时开启Secure属性
SESSION_COOKIE_SAMESITE = 'None'
SESSION_COOKIE_SECURE = True
# 若使用CSRF校验,同步调整CSRF Cookie配置
CSRF_COOKIE_SAMESITE = 'None'
CSRF_COOKIE_SECURE = True

注意该方案仅支持HTTPS站点,且对2020年之前发布的旧版本浏览器存在兼容性问题。

方案3(增加中间跳转页)

邮件中发送的链接改为无敏感参数的中间页地址,页面上放置「重置密码」按钮,用户点击按钮后再跳转到带token的重置地址,完全规避邮件爬虫和中转跳转的影响,同时可以保留Django原生的所有安全逻辑。

内容的提问来源于stack exchange,提问作者run_the_race

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 15:45:02