Django で独自のログイン認証を実装します。
以前、Django でログイン認証の記事を書きました。その時は、Django 標準の認証機能を使ったものでした。アプリケーションを新規で開発する場合は、それで良いですが、すでに認証システムは存在していて、例えば、認証 API は存在していて、それを利用したい場合があると思います。今回はそういうケースを想定しています。
Contents
バージョン
- Python 3.5.4
- Django 2.2.1
インストール
今回の環境は簡易的な環境ですので、Mac で virtualenv を使っています。
本格的に開発する場合は、Vagrant 等で VM を作成してください。
virtualenv のインストールと Django のインストール
$ python -m venv venv $ source venv/bin/activate (venv) $ pip install django
virtualenv をインストールし、有効にします。その後 Django をインストールします。
Django プロジェクトの作成
(venv) $ django-admin startproject custom_auth_backend
Django をインストールしたら、プロジェクトを作成します。custom_auth_backend という名前にしました。
Django アプリケーションの作成
(venv) $ cd custom_auth_backend (venv) $ python mange.py startapp auth_backend
プロジェクトを作成したら、次は、アプリケーションを作成します。auth_backend という名前にしました。
実装
settings.py
... ALLOWED_HOSTS = ['*'] ... INSTALLED_APPS = [ ... 'auth_backend.apps.AuthBackendConfig' ] ... LANGUAGE_CODE = 'ja' ... LOGIN_REDIRECT_URL = '/' AUTHENTICATION_BACKENDS = ['auth_backend.backends.Backend']
settings.py です。ここで重要なのは、AUTHENTICATION_BACKENDS です。デフォルトは、Django 認証バックエンドの ‘django.contrib.auth.backend.ModelBackend’ になっていますので、ここを今回独自で作成するログイン認証バックエンドに変更します。
backends.py
from django.contrib.auth.models import User class Backend: def authenticate(self, request, username=None, password=None): """ Check the username/password and return a user. ここに独自の認証を実装する。 OK のであれば、user オブジェクトを返し、 NG であれば、None を返す """ custom_auth_result = False if custom_auth_result: try: user = User.objects.get(username=username) except User.DoesNotExist: user = User(username=username) user.save() return user else: return None def get_user(self, user_id): try: return User.objects.get(pk=user_id) except User.DoesNotExist: return None
settings.py の AUTHENTICATION_BACKENDS で変更したバックエンド backends.py です。authenticate() と get_user() の二つの関数を実装したクラスを定義する必要があります。Django のドキュメントに詳細が書いていますが、authenticate() のなかで、独自の認証を実装し、認証 OK であれば、User オブジェクトを返し、NG であれば、None を返すようにします。
その他の修正
上記ファイル以外に、以下のファイルを作成、修正しました。内容は前回とほぼ同じですので、省略したいと思います。
- urls.py
- login.html
- top.html
動作確認
(venv) $ python manage.py migrate Operations to perform: Apply all migrations: admin, auth, contenttypes, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying auth.0010_alter_group_name_max_length... OK Applying auth.0011_update_proxy_permissions... OK Applying sessions.0001_initial... OK (venv) $ python manage.py runserver Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). May 12, 2019 - 02:14:15 Django version 2.2.1, using settings 'custom_auth_backend.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C.
それでは、動作確認したいと思います。
まず最初に、DB を用意する必要がありますので、DB のマイグレーションを実行します。今回は、簡易的な環境ですので、DB は sqlite を使用しています。
DB のマイグレーションを実行したら、runserver を実行し、ブラウザで http://127.0.0.1:8000/login/ にアクセスします。
ログインページにアクセスしたら、適当にメールアドレスとパスワードを入力し、Sign inボタンを押します。
すると、エラーで弾かれますが、先ほどの backends.py で、custom_auth_result = False としているので、どんな正しいユーザ情報を入力しても、必ずエラーになります。独自の認証システムの結果を custom_auth_result に代入して利用する感じになります。
まとめ
Django で独自のログイン認証を実装しました。
Django で独自のログイン認証を実装する際の修正ポイントは大きく以下の2つです。
- settings.py の AUTHENTICATION_BACKENDS を修正
- 独自の backends.py を作成
- authenticate()
- get_user()
独自のログイン認証を実装する場合は、おそらくユーザ情報も修正する必要が出てくると思います。独自ユーザの実装については、別の機会に説明したいと思います。