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

如何基于graphene-django实现密码重置邮件发送?

Django 内置的 django.contrib.auth 模块本身就提供了密码重置全流程的可直接调用组件,完全不需要依赖第三方包,你可以直接在 Graphene 的 Mutation 中封装调用,和你之前迁移登录时用的authenticate、login方法一样稳定,和原有认证体系完全兼容。

核心依赖的内置组件

你不需要自己实现令牌生成、邮件发送、安全校验这些逻辑,直接复用Django官方维护的成熟实现即可:

  • django.contrib.auth.tokens.PasswordResetTokenGenerator:内置的密码重置令牌生成/校验器,生成的令牌单次有效、带过期机制,和Django原生模板视图用的令牌逻辑完全一致,不存在安全兼容问题。
  • django.contrib.auth.forms.PasswordResetForm:封装了完整的邮箱校验、重置邮件发送逻辑,自动适配你settings里的邮件配置,不会因为传入不存在的邮箱抛出异常,天然防用户邮箱枚举。
  • django.contrib.auth.forms.SetPasswordForm:封装了密码强度校验、密码更新逻辑,和你后台改密码的校验规则完全统一。
具体实现步骤

1. 基础配置

首先在settings.py里补充必要配置,和你之前Django模板版本的配置保持一致即可:

# 邮件配置沿用你原有项目的配置即可
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
DEFAULT_FROM_EMAIL = "noreply@your-project-domain.com"
# 配置React端的密码重置页面地址,邮件里的链接会直接跳转到前端页面
FRONTEND_RESET_PASSWORD_PATH = "https://your-frontend-domain/reset-password"

2. 实现发送重置邮件的Mutation

import graphene
from django.conf import settings
from django.contrib.auth.forms import PasswordResetForm

class SendPasswordResetEmail(graphene.Mutation):
    success = graphene.Boolean(required=True)

    class Arguments:
        email = graphene.String(required=True)

    def mutate(self, info, email):
        form = PasswordResetForm(data={"email": email})
        if form.is_valid():
            request = info.context
            form.save(
                request=request,
                use_https=request.is_secure(),
                from_email=settings.DEFAULT_FROM_EMAIL,
                # 如果你要自定义邮件模板,替换成自己的模板路径即可
                email_template_name="registration/password_reset_email.html",
                extra_email_context={
                    "frontend_reset_path": settings.FRONTEND_RESET_PASSWORD_PATH
                }
            )
        # 无论邮箱是否存在都返回成功,避免攻击者枚举系统内的注册邮箱
        return SendPasswordResetEmail(success=True)

3. 实现提交新密码的Mutation

用户点击邮件里的前端链接,跳转到React重置页面后,前端拿到url里的uid和token参数,和用户输入的新密码一起传给这个接口即可:

import graphene
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import SetPasswordForm
from django.contrib.auth.tokens import default_token_generator
from django.utils.http import urlsafe_base64_decode

User = get_user_model()

class ResetPassword(graphene.Mutation):
    success = graphene.Boolean(required=True)
    error_msg = graphene.String()

    class Arguments:
        uidb64 = graphene.String(required=True)
        token = graphene.String(required=True)
        new_password = graphene.String(required=True)

    def mutate(self, info, uidb64, token, new_password):
        user = None
        try:
            uid = urlsafe_base64_decode(uidb64).decode()
            user = User.objects.get(pk=uid)
        except (TypeError, ValueError, OverflowError, User.DoesNotExist):
            pass

        # 直接调用内置方法校验令牌有效性、是否过期
        if user and default_token_generator.check_token(user, token):
            form = SetPasswordForm(
                user=user,
                data={"new_password1": new_password, "new_password2": new_password}
            )
            if form.is_valid():
                form.save()
                return ResetPassword(success=True, error_msg=None)
            return ResetPassword(success=False, error_msg=form.errors.as_text().split("\n")[0])
        return ResetPassword(success=False, error_msg="重置链接无效或已过期,请重新申请重置邮件")
注意事项
  • 所有逻辑完全复用Django内置auth的官方实现,没有额外的依赖维护成本,稳定性和你已经上线的登录逻辑一致。
  • 如果需要自定义邮件内容,只需要自己写邮件模板替换默认模板即可,模板中可以直接拿到uid、token、frontend_reset_path变量,拼接成前端跳转链接即可,示例链接格式:{{ frontend_reset_path }}?uid={{ uid }}&token={{ token }}。
  • 这套实现不需要修改你现有项目的任何认证配置,迁移成本极低。

内容的提问来源于stack exchange,提问作者NICOLÁS ANTONIO PINO LEVA

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 02:27:19