Django 重置密码
大家好!
除了登录和注销视图之外,Django 的身份验证应用还提供了允许用户在忘记密码时重置密码的视图。让我们继续看看如何在应用中添加此功能。
工作流程:
1) 用户点击“忘记密码”链接 - 这将把他们带到一个页面,提示他们输入电子邮件地址。此视图将通过扩展内置的 来处理PasswordResetView
。
PasswordResetView
- 此视图显示用户提交其电子邮件地址的表单 -> 检查数据库中是否存在具有所提供电子邮件地址的用户 -> 生成仅使用一次的密码重置链接 -> 最后将该链接发送到用户的电子邮件地址。
- 注意- 如果提供的电子邮件地址未与任何用户关联,Django 不会抛出错误,但不会发送电子邮件,您可能想知道为什么,原因是为了“防止信息泄露给潜在的攻击者”。如果您不喜欢此功能,而希望让用户知道他们何时输入了正确的电子邮件地址,何时输入了错误的电子邮件地址,您可以随时从该类继承
PasswordResetForm
并对其进行一些自定义。
那么,为什么不直接使用这个视图,而是通过扩展它来创建我们自己的视图呢?
- 下面让我们看一下代码并进行讨论。
视图.py
from django.urls import reverse_lazy
from django.contrib.auth.views import PasswordResetView
from django.contrib.messages.views import SuccessMessageMixin
class ResetPasswordView(SuccessMessageMixin, PasswordResetView):
template_name = 'users/password_reset.html'
email_template_name = 'users/password_reset_email.html'
subject_template_name = 'users/password_reset_subject'
success_message = "We've emailed you instructions for setting your password, " \
"if an account exists with the email you entered. You should receive them shortly." \
" If you don't receive an email, " \
"please make sure you've entered the address you registered with, and check your spam folder."
success_url = reverse_lazy('users-home')
template_name
- 如果没有给出任何内容,django 默认使用 registry/password_reset_form.html 来呈现视图的相关模板,但由于我们的模板将位于我们的用户应用程序模板目录中,所以我们需要明确地告诉 django。email_template_name
- 用于生成带有重置密码链接的电子邮件正文的模板。subject_template_name
- 用于生成带有重置密码链接的电子邮件主题的模板。success_message
- 密码重置请求成功后将显示的消息。success_url
- 如果没有指定,Django 在密码请求成功后默认使用“password_reset_done”。但我认为直接将用户重定向到主页而不提供任何其他模板是合理的。
我们尚未设置我们的应用程序来发送电子邮件,但我们稍后会这样做。
-> 将此视图映射到我们主项目的 url 模式。
用户管理/urls.py
from django.urls import path
from users.views import ResetPasswordView
urlpatterns = [
path('password-reset/', ResetPasswordView.as_view(), name='password_reset'),
]
-> 现在让我们提供与视图相关的模板。在 users/templates/users/ 目录中创建以下模板。
密码重置.html
{% extends "users/base.html" %}
{% block content %}
<div class="form-content my-3 p-3">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-5">
<div class="card shadow-lg border-0 rounded-lg mt-0 mb-3">
<div class="card-header justify-content-center">
<div id="error_div"></div>
<h3 class="font-weight-light my-4 text-center">Forgot Password?</h3>
</div>
{% if form.errors %}
<div class="alert alert-danger alert-dismissible" role="alert">
<div id="form_errors">
{% for key, value in form.errors.items %}
<strong>{{ value }}</strong>
{% endfor %}
</div>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
<div class="card-body">
<form method="POST">
{% csrf_token %}
<div class="form-row">
<div class="col-md-10 offset-md-1">
<div class="form-group">
<label class="small mb-1" for="id_email">Email</label>
<input type="email" name="email" class="form-control"
autocomplete="email" maxlength="254" required id="id_email"
placeholder="Enter email">
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-10 offset-md-1">
<div class="form-group mt-0 mb-1">
<button type="submit" class="col-md-12 btn btn-dark">Submit
</button>
</div>
</div>
</div>
</form>
</div>
<div class="card-footer text-center">
<div class="small">
<a href="{% url 'users-register' %}">Create A New Account</a><br><br>
<a href="{% url 'login' %}">Back To Login</a><br>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
密码重置电子邮件.html
{% autoescape off %}
To initiate the password reset process for your {{ user.email }} Django Registration/Login App Account,
click the link below:
{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
If clicking the link above doesn't work, please copy and paste the URL in a new browser
window instead.
Sincerely,
The Developer
{% endautoescape %}
密码重置主题.txt
Django - Registration/Login App Password Reset
-> 修改login.html中的死链接以指向password_reset。
登录.html
<a href="{% url 'password_reset' %}"><i>Forgot Password?</i></a>
2) 密码重置请求完成后,用户将被重定向到主页,并显示一条消息,提示用户查看邮箱地址。请注意,正如我之前提到的,即使请求重置密码的用户不存在,也会显示此消息。
3) 用户前往邮箱查看邮件。假设一切顺利,用户收到了设置密码的说明。邮件内容如下:
4) 用户点击生成的链接,将获得一个输入新密码的表单。
PasswordResetConfirmView
是负责呈现此密码重置表单并验证令牌的视图,即令牌是否已过期,或者是否已被使用。
-> 将其映射PasswordResetConfirmView
到我们主项目的 url 模式。
用户管理/urls.py
from django.urls import path
from django.contrib.auth import views as auth_views
urlpatterns = [
path('password-reset-confirm/<uidb64>/<token>/',
auth_views.PasswordResetConfirmView.as_view(template_name='users/password_reset_confirm.html'),
name='password_reset_confirm'),
]
URL 的参数是什么?
- uidb64:以 base 64 编码的用户 ID。
- token:密码恢复令牌,用于检查密码是否有效。
-> 现在,让我们为该视图提供模板。继续在我们的用户应用模板目录中创建password_reset_confirm.html 。
密码重置确认.html
{% extends "users/base.html" %}
{% block title %} Password Reset {% endblock title%}
{% block content %}
<div class="form-content my-3 p-3">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-5">
{% if validlink %}
<div class="card shadow-lg border-0 rounded-lg mt-0 mb-3">
<div class="card-header justify-content-center">
<h3 class="font-weight-light my-4 text-center">Reset Your Password</h3>
</div>
{% if form.errors %}
<div class="alert alert-danger alert-dismissible" role="alert">
<div id="form_errors">
{% for key, value in form.errors.items %}
<strong>{{ value }}</strong>
{% endfor %}
</div>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
<div class="card-body">
<form method="POST">
{% csrf_token %}
<div class="form-row">
<div class="col-md-10 offset-md-1">
<div class="form-group">
<label class="small mb-1" for="id_new_password1">New Password</label>
<input type="password" name="new_password1" autocomplete="new-password"
class="form-control" required id="id_new_password1"
placeholder="Enter password"/>
<span>
</span>
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-10 offset-md-1">
<div class="form-group">
<label class="small mb-1" for="id_new_password2">New Password Confirmation</label>
<input type="password" name="new_password2" autocomplete="new-password"
required id="id_new_password2" class="form-control"
placeholder="Confirm password"/>
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-10 offset-md-1">
<div class="form-group mt-0 mb-1">
<button type="submit" class="col-md-12 btn btn-dark" id="reset">Reset Password</button>
</div>
</div>
</div>
</form>
</div>
</div>
{% else %}
<div class="alert alert-warning">
The password reset link was invalid, possibly because it has already been used.
Please request a new password reset.
</div>
{% endif %}
</div>
</div>
</div>
</div>
{% endblock content %}
5)如果密码重置成功,PasswordResetCompleteView
将显示一个视图,让用户知道他/她的密码已成功更改。
-> 将此视图映射到我们主项目的 url 模式。
用户管理/urls.py
from django.urls import path
from django.contrib.auth import views as auth_views
urlpatterns = [
path('password-reset-complete/',
auth_views.PasswordResetCompleteView.as_view(template_name='users/password_reset_complete.html'),
name='password_reset_complete'),
]
-> 提供 PasswordResetCompleteView 的模板
密码重置完成.html
{% extends "users/base.html" %}
{% block content %}
<div class="container my-3 p-3">
<div class="row justify-content-center">
<div class="col-lg-5">
<div class="card shadow-lg border-0 rounded-lg mt-0 mb-3">
<div class="alert alert-info">
Your password has been set. You may go ahead and <a href="{% url 'login' %}">Login Here</a>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
在 Django 中设置发送电子邮件
我们已经配置了 django 让用户重置密码所需的一切,但我们实际上并没有向用户发送电子邮件,所以让我们继续这样做。
选项 1 - 建议您为您的 Google 帐户启用双重身份验证 (2FA),以便我们的应用能够发送电子邮件。请点击此链接进行设置。
选项 2 - 但如果您不想启用 2FA,那么只需转到此处并允许您的 Google 帐户使用安全性较低的应用程序。
更新: 自 2022 年 5 月 30 日起,“安全性较低的应用”设置将不再可用。点击此处了解原因。
好的,接下来转到settings.py并添加以下内容。
设置.py
# email configs
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = str(os.getenv('EMAIL_USER'))
EMAIL_HOST_PASSWORD = str(os.getenv('EMAIL_PASSWORD'))
EMAIL_BACKEND
是电子邮件将通过的 SMTP 后端。EMAIL_HOST
是用于发送电子邮件的主机。EMAIL_USE_TLS
- 与 SMTP 服务器通信时是否使用 TLS(安全)连接。这用于显式 TLS 连接,通常在端口 587 上。EMAIL_PORT
- EMAIL_HOST 中定义的 SMTP 服务器使用的端口。EMAIL_HOST_USER
和EMAIL_HOST_PASSWORD
分别是 SMTP 服务器的用户名和密码。为了保证它们的安全,请将它们放在.env文件中,并在此处获取它们,就像我们在本系列上一篇中介绍的那样。
它是否正常工作?
python manage.py runserver
启动开发服务器并在终端中运行常用命令。- 访问 localhost 看看是否正常。遇到任何问题?欢迎随时咨询我。
感谢您抽出时间。您可以在GitHub上找到已完成的应用程序。我们下次再见,继续本系列的其他部分。
文章来源:https://dev.to/earthcomfy/django-reset-password-3k0l