На сайтах, где реализуется функционал регистрации пользователя, так же создается и процедура восстановления пароля. Процесс восстановления пароля выполняется из нескольких шагов. Это, например, переход по специальной ссылке, которая высылается в письме. Так как это стандартный функционал для множества сайтов - в Django уже есть простой способ это реализовать. Как это можно сделать и будет рассмотрено на примерах.
Как реализуется процесс восстановления пароля
Хоть процесс восстановления пароля - это процедура, через которую все проходили, многие не замечают что она реализуется через несколько страниц:
- Страница ввода учетных данных;
- Страница, которая подтверждает, что учетные данные найдены и ссылка для восстановления пароля выслана;
- Страница, на которую переходят по ссылке из письма для смены пароля. Переход на эту страницу выполняется через уникальный URL;
- Страница об успешной смене пароля.
Так как это обычная задача для большинства сайтов в Django уже есть способ сделать это простым способом. В модуле 'django.contrib.auth.urls', кроме возможности login и logout (и других возможностей), так же реализована задача по восстановлению пароля. Процесс по восстановлению пароля, через этот модуль, строится на следующих путях:
- accounts/password_reset/ [name='password_reset']
- accounts/password_reset/done/ [name='password_reset_done']
- accounts/reset/<uidb64>/<token>/ [name='password_reset_confirm']
- accounts/reset/done/ [name='password_reset_complete']
Ссылка отправляется - через раннее настроенный SMTP аккаунт. Для тестирования есть возможность вывода ссылки в лог Django.
Обратите внимание, что хоть в Django, по умолчанию, идентификация пользователя выполняется по его логину (имени пользователя), процедура восстановления пароля требует адрес почты.
Тестовый проект
В примерах ниже используется самый простой проект на Django 4.1. Вы можете создать его следующими командами.
django-admin startproject testproject
cd .\testproject\
python manage.py migrate
python manage.py createsuperuser
Создание маршрутов в urls.py
Маршруты, для страниц по восстановлению паролей, можно создать двумя способами.
Первый способ будет включать в себя дополнительные маршруты, которые предназначаются для входа и выхода, регистрации и смены пароля. Выбирайте его, если вам так же нужно реализовать остальные возможности.
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('django.contrib.auth.urls')),
]
Второй способ включает в себя только пути, которые связаны с процедурой восстановления пароля.
from django.contrib import admin
from django.urls import path
from django.contrib.auth import views as auth_views
urlpatterns = [
path('admin/', admin.site.urls),
path('reset_password/', auth_views.PasswordResetView.as_view(),
name ='reset_password'),
path('reset_password_sent/', auth_views.PasswordResetDoneView.as_view(),
name ='password_reset_done'),
path('reset/<uidb64>/<token>', auth_views.PasswordResetConfirmView.as_view(),
name ='password_reset_confirm'),
path('reset_password_complete/', auth_views.PasswordResetCompleteView.as_view(),
name ='password_reset_complete'),
]
В первом варианте, названия путей (параметр name), такие же, что и во втором.
Путь 'reset/<uidb64>/<token>' используется для ссылки, по которой будет переходить пользователь. Через вьюшку 'PasswordResetView' такая ссылка будет сгенерирована и выслана на почту. Ссылка состоит из двух параметров:
- uidb64 - закодированный base64 идентификатор пользователя;
- token - хэш сумма из идентификатора пользователя, секрета, временной метки и др.
Создание шаблонов
Для каждого из путей должен быть создан шаблон. Общая папка, для хранения всех шаблонов, указывается в файле 'testproject/settings.py'. В примере для статьи указан следующий путь:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
...
},
]
Шаблоны для процесса восстановления пароля, создаются в дополнительной папке 'registration' и имеют следующие имена.
- password_reset_form.html
- password_reset_subject.txt - тема письма
- password_reset_email.html - тело письма
- password_reset_done.html
- password_reset_confirm.html
- password_reset_complete.html
Шаблон запроса на сброс пароля
По пути 'registration/password_reset_form.html' создается шаблон, который используется для создания запроса по восстановлению. Самая простая реализация этого шаблона следующая:
{% block content %}
<h3>Восстановление пароля</h3>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Отправить</button>
</form>
{% endblock %}
Если email будет найден - пользователь будет переадресован на URL 'reset_password_sent'. Шаблон для этой страницы должен располагаться по пути 'registration/password_reset_done.html'. Пример содержания:
{% block content %}
Инструкция по восстановлению пароля отправлена на указанный email
{% endblock %}
Шаблон отправляемого письма
Письмо состоит из темы и содержания. Для каждого из них создается отдельный шаблон. В каждом из них могут быть использованы переменные, которые используются в обычных шаблонах. Это, например, переменная 'user' или 'domain', которые могли бы лучше конкретизировать письмо.
Пример темы сообщения, указанный в файле 'registration/password_reset_subject.txt':
Восстановление пароля пользователя {{ user.get_username }} для {{ domain }}
Заголовок, который будет выводиться при отладке, может начинаться с атрибута '=?utf-8', указывающим на кодировку. Такой формат соответствует RFC 2047. Такая ситуация не касается латиницы.
Пример тела сообщения, указанный в файле 'registration/password_reset_email.html':
{% autoescape off %}
Восстановление пароля для пользователя {{ user.get_username }}. Перейдите по следующей ссылке:
{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uid64=uid token=token %}
{% autoescape on %}
Шаблон смены пароля
Ссылка в письме ведет на страницу с формой для смены пароля. Этот шаблон должен лежать по пути 'registration/password_reset_confirm.html'. В этом же шаблоне идет проверка на действительность ссылки, по которой был выполнен переход. Это действие выполняется через переменную 'validlink'.
{% block content %}
{% if validlink %}
<h1>Смена пароля</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Подтвердить</button>
</form>
{% else %}
<p>
Вероятно ссылка неверна или уже была использована
</p>
{% endif %}
{% endblock %}
Если смена пароля прошла успешно - будет открыт шаблон 'registration/password_reset_complete.html'.
{% block content %}
<p>Пароль для пользователя успешно сменен</p>
{% endblock %}
Смена языка
Поля некоторых форм отображаются на английском языке. Один из способов это изменить - указать нужный язык проекта в файле 'testproject/settings.py'.
LANGUAGE_CODE = 'ru-RU'
Изменения путей и имени шаблонов
Вы можете изменить путь, по которому можно найти шаблон, заполнив 'template_name' в файле 'urls.py':
from django.contrib import admin
from django.urls import path
from django.contrib.auth import views as auth_views
urlpatterns = [
path('admin/', admin.site.urls),
path('reset_password/', auth_views.PasswordResetView.as_view(template_name='test.html'),
name ='reset_password'),
]
Настройка отправки писем через SMTP
Для отправки писем у вас должны быть указаны настройки пользователя и сервер. Если этого не сделано, но вы уже пытались восстановить пароль, то на моменте отправки письма появится ошибка:
- [WinError 10061] Подключение не установлено, т.к. конечный компьютер отверг запрос на подключение
- [WinError 10061] No connection could be made because the target machine actively refused it
Для тестирования отправки писем, без настройки самого аккаунта, можно выполнить ряд настроек, которые устанавливаются в файле 'testproject/settings.py'.
Следующая настройка будет выводить письма в консоли.
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
Следующая - сохранять их в папке 'emails' в корне проекта.
EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = BASE_DIR / 'emails'
Если вы хотите отправлять письма другим пользователям, то вам нужно так же заполнить ряд параметров. Это делается в этом же файле. Вам потребуется указать данные SMTP сервера и пользователя от имени которого будут отправляться письма. Пример полей, которые вам нужно будет указать ниже, но они могут отличаться от используемого сервера.
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'test@gmail.com'
EMAIL_HOST_PASSWORD = '123'
...
Подписывайтесь на наш Telegram канал
Теги: #python #django #пользователи #пароль