【django】ログイン認証機能:パスワードリセット機能を組み込む方法
2021.04.09 /
本記事では、PythonのWebフレームワークdjangoを使ったログイン認証機能における、アカウントのパスワードをリセットする機能を組み込む方法について解説していきます。
djangoにはWebアプリケーションで必須となるログイン認証機能が最初から備わっています。一から作成するには時間がかかるパスワードリセット機能もdjangoには用意されています。
パスワードのリセット機能はWebアプリケーションに組み込むのは非常に簡単ですが、仕組みを理解するのが少し難しいです。
初めてパスワードリセット機能を使う方にもわかるように、詳しく説明していきたいと思います。
本記事を通して以下の知識を学べます。
- ログイン認証機能を提供しているdjango.contrib.authについて
- パスワードリセットで使用する4つのビューの使い方
- メールの送信設定について
Djangoに組み込まれているパスワードリセット機能
冒頭でも説明していますが、djangoにはインストールしたらすぐに使えるログイン認証機能が用意されています。
ここではログイン認証に使われるパスワードをリセットする機能について解説していきます。
パスワードリセット機能とは
初めてログイン認証機能を含んだWebアプリケーションを作成する人には、パスワードリセット機能がそもそも何かわからないかもしれないです。
パスワードリセットとは、パスワードを忘れた場合に、パスワードを再設定できるようにした機能のことです。
パスワードリセットの流れ
パスワードリセットでは、Webアプリケーションのみで行えるわけでなくメールも使用します。
ユーザーの登録しているメールアドレス宛にパスワードリセットページのURLが送られます。
そのURLからパスワード更新ページへ移動し、新しいパスワードを入力します。
まとめるとユーザーは以下の流れでパスワードをリセットできます。
- パスワードリセットページでメールアドレスを入力
- メール送信完了ページが表示され、パスワードリセットメールを受信
- メールに記載されているリンクをクリック
- パスワード更新ページから新パスワードを設定
- パスワード更新完了ページが表示
上記のパスワードリセットの流れを理解していただくと、プログラムを組むのがスムーズに進みます。
次にパスワードリセットで使用するビューについて解説します。
django.contrib.auth
ログインやログアウト、パスワード変更、パスワードリセットなどのログイン認証機能は、django.contrib.authアプリケーションが提供しています。
仮想環境venvでは、以下のようなパスに保存されています。
venv\Lib\site-packages\django\contrib\auth\
ログイン認証機能は、authアプリケーション内のviews.pyに使用するビューが記載されています。
django.contrib.auth.views
django.contrib.auth内のviews.pyに記載されているクラスビューを使用して、ログイン認証機能が簡単に実現できます。
djangoに備わっているパスワードリセットでは、以下4つのビューを使用します。
- PasswordResetView
- PasswordResetDoneView
- PasswordResetConfirmView
- PasswordResetCompleteView
これらビューを使用するために、必ずプログラムの先頭でdjango.contrib.authからviewsをインポートするようにしてください。
from django.contrib.auth import views as auth_views
パスワードリセットで使用する4つのビューについて以下で解説します。
PasswordResetView
PasswordResetViewは、パスワードリセットのメールを送信するビューです。
テンプレートで使用する、パスワード入力用Form(PasswordResetForm)が用意されています。
メールに送られる本文も用意されていますので、文面を用意する必要もありません。
class PasswordResetView(PasswordContextMixin, FormView):
email_template_name = 'registration/password_reset_email.html'
extra_email_context = None
form_class = PasswordResetForm
from_email = None
html_email_template_name = None
subject_template_name = 'registration/password_reset_subject.txt'
success_url = reverse_lazy('password_reset_done')
template_name = 'registration/password_reset_form.html'
title = _('Password reset')
token_generator = default_token_generator
from_emailがデフォルトではNoneになっているため、実際に使用する際にはfrom_emailにメールアドレスを入れる必要はあります。
また入力されたメールアドレスのユーザーがアクティブ(is_activeがTrue)の場合のみにメールは送信されます。
メール送信が完了すると、URLconfの名前がpassword_reset_doneにページ遷移します。
PasswordResetDoneView
PasswordResetDoneViewは、メール送信後に表示されるページを表示するビューです。
class PasswordResetDoneView(PasswordContextMixin, TemplateView):
template_name = 'registration/password_reset_done.html'
title = _('Password reset sent')
PasswordResetConfirmView
PasswordResetConfirmViewは、受信したメールのURLをクリックすると表示されるパスワード更新ページを表示します。
表示されるページに新しく設定したいパスワードを入力します。
class PasswordResetConfirmView(PasswordContextMixin, FormView):
form_class = SetPasswordForm
post_reset_login = False
post_reset_login_backend = None
reset_url_token = 'set-password'
success_url = reverse_lazy('password_reset_complete')
template_name = 'registration/password_reset_confirm.html'
title = _('Enter new password')
token_generator = default_token_generator
post_reset_loginをTrueにすると、新しいパスワードを設定した後に、そのままログイン処理が行われます。デフォルト値はFalseです。
パスワード設定がが完了すると、URLconfの名前がpassword_reset_completeにページ遷移します。
PasswordResetCompleteView
PasswordResetCompleteViewは、パスワードのリセット処理が完了すると表示される、リセット完了ページを表示します。
class PasswordResetCompleteView(PasswordContextMixin, TemplateView):
template_name = 'registration/password_reset_complete.html'
title = _('Password reset complete')
メール送信設定
Webアプリケーションからパスワードリセットのためのメールを送信する必要があります。
そのためsettings.pyにメール送信サーバー情報を追加する必要があります。
以下にgmailの場合での設定例を記載します。
#Mail Setting
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'gmailアカウント名'
EMAIL_HOST_PASSWORD = 'パスワード'
EMAIL_USE_TLS = True
詳しくは以下記事をご参照ください。
【Django】簡単にメール送信機能を追加する方法(単一送信・複数送信・ファイル添付)
パスワードリセット機能を追加してみよう
では実際にWebアプリケーションにパスワードリセット機能を追加しましょう。
以下記事で作成したWebアプリケーションに対してパスワードリセット機能を追加します。
【django】ログイン認証機能:パスワード変更機能を組み込む方法
次の流れでパスワードリセット機能を追加していきます。
- urls.pyにルーティングを追加
- テンプレートの追加(4ページ)
- settings.pyにメール送信サーバー情報を追加
- login.htmlにパスワードリセットページへのリンクを追加
画面遷移
パスワードリセット機能を追加して完成する、Webアプリケーションの画面遷移を以下に記します。
- ログインページ
- パスワードリセットページ
- メール送信完了ページ
- パスワード更新ページ
- パスワード更新完了ページ
送信されるパスワード更新ページのリンクを含むメールは、デフォルトだと次のような内容です。
You're receiving this email because you requested a password reset for your user account at 127.0.0.1:8000.
Please go to the following page and choose a new password:
link
Your username, in case you’ve forgotten: root
Thanks for using our site!
The 127.0.0.1:8000 team
urls.pyにルーティングを追加
まずはプロジェクトのurls.pyに以下4つのURLルーティングを追加します。
path('accounts/password_reset_form/', auth_views.PasswordResetView.as_view(template_name='registration/password_reset.html', from_email=' office54@office54.net '), name='password_reset'),
path('accounts/password_reset_done/', auth_views.PasswordResetDoneView.as_view(template_name='registration/password_reset_mail_done.html'), name='password_reset_done'),
path('accounts/password_reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(template_name='registration/password_reset_confirmation.html'), name='password_reset_confirm'),
path('accounts/password_reset_finish/', auth_views.PasswordResetCompleteView.as_view(template_name='registration/password_reset_finish.html'), name='password_reset_complete'),
パスワードリセットで使用する4つのビューへのルーティングを追加しました。
各ルーティングではオプションtemplate_nameを使って、クラスで使用するテンプレートを指定しています。
すでに備わっているクラスを使用しているので、views.pyへの記入は一切必要ありません。
テンプレートの追加
パスワードリセットで表示される4つのテンプレートを作成します。
password_reset_confirmation.html
{% extends "five/base.html" %}
{% block content %}
<h2>Password Reset Form</h2>
<form method="post" style="padding-left:20px;">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Reset Password</button>
</form>
{% endblock %}
password_reset_mail_done.html
{% extends "five/base.html" %}
{% block content %}
<h2>Your password reset Email has been sent.</h2>
{% endblock %}
password_reset.html
{% extends "five/base.html" %}
{% block content %}
<h2>Password Reset Form</h2>
<form method="post" style="padding-left:20px;">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Reset Password</button>
</form>
{% endblock %}
password_reset_finish.html
{% extends "five/base.html" %}
{% block content %}
<h2>Password reset complete</h2>
<p>Your password has been set. You may go ahead and log in now.</p>
<p><a href="{% url 'login' %}">Login</a></p>
{% endblock %}
settings.pyにメール設定を追加
settings.pyにメール送信サーバー情報を追加してください。
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'office54@office54.net'
EMAIL_HOST_PASSWORD = '54545454'
EMAIL_USE_TLS = True
ソースコード
その他のページで変更した点を以下に記します。
コピペして実際に動く様子を確認してください。
login.html
{% extends "five/base.html" %}
{% block content %}
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
<p><a href="{% url 'password_reset' %}">Forgot Your Password?</a></p> # 追加
{% endblock %}
urls.py:プロジェクト
from django.contrib import admin
from django.urls import path, include
from django.contrib.auth import views as auth_views
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('five.urls')),
path('accounts/', include('django.contrib.auth.urls')),
path('accounts/password_change_form/', auth_views.PasswordChangeView.as_view(template_name='registration/password_change.html'), name='password_change_form'),
path('accounts/password_change_done/', auth_views.PasswordChangeDoneView.as_view(template_name='registration/password_change_finish.html'), name='password_change_done'),
path('accounts/password_reset_form/', auth_views.PasswordResetView.as_view(template_name='registration/password_reset.html', from_email='admin-scan@system.benline.co.jp'), name='password_reset'), # 追加
path('accounts/password_reset_done/', auth_views.PasswordResetDoneView.as_view(template_name='registration/password_reset_mail_done.html'), name='password_reset_done'), # 追加
path('accounts/password_reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(template_name='registration/password_reset_confirmation.html'), name='password_reset_confirm'), # 追加
path('accounts/password_reset_finish/', auth_views.PasswordResetCompleteView.as_view(template_name='registration/password_reset_finish.html'), name='password_reset_complete'), # 追加
]
まとめ
本記事「【django】ログイン認証機能:パスワードリセット機能を組み込む方法」はいかがでしたか。
djangoに備わっている機能を使うことで、実装するのが難しいリセット機能が簡単にできました。
このように一から作ると時間がかかる機能も簡単に実装できるのが、フレームワークの良さの一つですよね。
ぜひみなさんもご自身のWebアプリケーションにパスワードリセット機能を組み込んでみてください。