
本文详解如何在 django rest framework 中实现用户密码重置(忘记密码)和密码修改功能,说明为何 drf 不内置这些 api、推荐的第三方方案及自定义实现要点。
本文详解如何在 django rest framework 中实现用户密码重置(忘记密码)和密码修改功能,说明为何 drf 不内置这些 api、推荐的第三方方案及自定义实现要点。
Django REST Framework(DRF)本身聚焦于构建灵活、可扩展的 API 层,并不直接提供“开箱即用”的业务级认证服务(如密码找回、邮箱验证、双因素登录等)。其设计哲学是:认证(Authentication)仅负责“你是谁”,而授权(Authorization)与用户生命周期管理(如密码重置)属于业务逻辑层,需由开发者根据实际场景定制。因此,/api/password/reset/ 或 /api/password/change/ 这类端点不会自动存在——这不是功能缺失,而是架构上的有意留白。
✅ 推荐方案:优先使用成熟第三方包
DRF 官方文档明确推荐了多个经生产验证的第三方认证扩展包,其中最常用的是:
- dj-rest-auth:轻量、活跃维护,原生支持 Login, Logout, Password Reset, Password Change, User Details 等标准端点,且与 Django 的 PasswordResetForm 和邮件后端无缝集成。
- django-allauth + dj-rest-auth:若需社交登录(Google/GitHub)、邮箱确认等更复杂流程,建议组合使用。
安装与基础配置示例:
pip install dj-rest-auth django-allauth
# settings.py
INSTALLED_APPS += [
'django.contrib.sites',
'allauth',
'allauth.account',
'dj_rest_auth',
'dj_rest_auth.registration',
]
SITE_ID = 1
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' # 开发时打印邮件内容
REST_AUTH = {
'USE_JWT': True,
'JWT_AUTH_HTTPONLY': False,
}# urls.py
from django.urls import path, include
urlpatterns = [
path('api/auth/', include('dj_rest_auth.urls')),
path('api/auth/registration/', include('dj_rest_auth.registration.urls')),
]此时将自动启用以下标准端点:
- POST /api/auth/password/reset/ → 提交邮箱触发重置邮件
- POST /api/auth/password/reset/confirm/ → 提交 uidb64 + token + 新密码完成重置
- POST /api/auth/password/change/ → 需认证(Token/JWT),提交旧密码与新密码
⚠️ 注意事项:
- 生产环境务必配置真实的 EMAIL_BACKEND(如 SMTP 或 SendGrid);
- dj-rest-auth 默认依赖 django.contrib.sites,SITE_ID=1 必须存在;
- JWT 模式下,password/change/ 要求请求头携带 Authorization: Bearer
; - 所有密码重置链接默认为 HTTP 协议,如部署在 HTTPS 环境,需设置 ACCOUNT_DEFAULT_HTTP_PROTOCOL = 'https'。
?️ 自定义实现(进阶):何时以及如何动手写?
当项目有特殊需求时(例如:短信验证码重置、多步骤安全验证、审计日志强制记录),建议基于 DRF 的 APIView 或 ViewSets 自定义:
# views.py
from django.contrib.auth.forms import SetPasswordForm
from django.contrib.auth.tokens import default_token_generator
from django.utils.http import urlsafe_base64_decode
from rest_framework import status, generics
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
class PasswordChangeView(generics.UpdateAPIView):
permission_classes = [IsAuthenticated]
serializer_class = PasswordChangeSerializer # 自定义序列化器校验旧密码
def update(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
request.user.set_password(serializer.validated_data['new_password'])
request.user.save()
return Response({'detail': 'Password updated successfully.'})核心原则:
- 复用 Django 内置密码逻辑(如 default_token_generator、PasswordResetForm)保证安全性;
- 所有敏感操作(如重置链接生成、密码哈希更新)必须在服务端完成,禁止前端参与 token 生成或密码明文传输;
- 始终对失败场景返回泛化提示(如“如果邮箱存在,您将收到重置邮件”),避免暴露用户注册状态。
总之,DRF 的“不提供”恰恰是其强大之处——它赋予你精确控制权。选择 dj-rest-auth 可快速落地标准流程;需要深度定制时,则依托 Django 安全基底自主构建。二者并非替代关系,而是演进路径。










