くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

DjangoでAPI(DRF)でパスワードを忘れたときの処理

Django Rest Frameworkを利用してるときに、
パスワードリセットをAPIでできるようにしたときの備忘録。

django-rest-passwordresetを使うと簡単にできる。
APIの画面も生成してくれるので、ブラウザでアクセスすると確認できる。

インストール

$ pip install django-rest-passwordreset

設定

settings.pyのINSTALLED_APPSにdjango_rest_passwordresetを追加。
django.contrib.authrest_frameworkが必要

INSTALLED_APPS = (
    ...
    'django.contrib.auth',
    ...
    'rest_framework',
    ...
    'django_rest_passwordreset',
    ...
)

DBをセットアップするため、マイグレーションが必要。

$ python manage.py migrate

使い方

URLへ追加

まずは、URLにincludeする。

from django.conf.urls import url, include


urlpatterns = [
    ...
    url(r'^api/password_reset/', include('django_rest_passwordreset.urls', namespace='password_reset')),
    ...
]  

includeすると以下のエンドポイントが作成されるので、あとはアクセスするだけ。
${API_URL}はinclude時に設定したURL。この例だと、api/password_reset/

`POST ${API_URL}/reset_password/``

  • パスワードリセット時のトークンを払い出すAPI
    emailを渡すとトークンが返ってくる
  • パラメタ: email

POST ${API_URL}/reset_password/confirm/

  • トークンを使って、パスワードを変更するAPI
    トークンと新しいパスワードを渡すとパスワード変更できる
  • パラメタ: token, password

POST ${API_URL}/reset_password/validate_token/

  • トークンが有効かどうかを検証するAPI
    トークンを渡すと、有効かどうかを返してくる。
  • パラメタ: token

小ネタ

トークン発行時にメールを送りたい

シグナルが用意されているので、それを受け取ったらメールを送る処理を追加すればOK。
この例では、email/user_reset_password.txtファイルをテンプレートとして、
メールを送っているので、templates/email/user_reset_password.txtを作成しておく。

from django.core.mail import EmailMultiAlternatives
from django.dispatch import receiver
from django.template.loader import render_to_string
from django.urls import reverse

from django_rest_passwordreset.signals import reset_password_token_created


@receiver(reset_password_token_created)
def password_reset_token_created(sender, instance, reset_password_token, *args, **kwargs):
    # send an e-mail to the user
    context = {
        'current_user': reset_password_token.user,
        'username': reset_password_token.user.username,
        'email': reset_password_token.user.email,
        'reset_password_url': "{}?token={}".format(reverse('password_reset:reset-password-request'), reset_password_token.key)
    }

    # render email text
    email_plaintext_message = render_to_string('email/user_reset_password.txt', context)

    msg = EmailMultiAlternatives(
        # title:
        "Password Reset for {title}".format(title="Some website title"),
        # message:
        email_plaintext_message,
        # from:
        "noreply@somehost.local",
        # to:
        [reset_password_token.user.email]
    )
    msg.send()

emailフィールド以外のフィールドにあるメールアドレスから探してほしい

settings.pyにDJANGO_REST_LOOKUP_FIELDを追加して設定する。

DJANGO_REST_LOOKUP_FIELD = 'custom_email_field'

以上!!

参考サイト