Django の認証システムでログイン・ログアウトを実装する
Django には認証システムが標準で組み込まれており、ユーザーの登録・ログイン・ログアウト・パスワード管理といった機能をゼロから書く必要がありません。django.contrib.auth が提供するビューとデコレータを使えば、数十行のコードで認証機能が完成します。
認証システムの初期設定
django-admin startproject で作成したプロジェクトには、認証に必要な設定がすでに含まれています。settings.py の INSTALLED_APPS に以下が入っていることを確認してください。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
django.contrib.auth が認証の本体、django.contrib.contenttypes と django.contrib.sessions が依存モジュールです。migrate を実行すれば、ユーザーテーブル(auth_user)をはじめとする認証関連のテーブルが自動で作成されます。
ログインの実装
Django は LoginView という汎用ビューを提供しています。URL の設定とテンプレートを用意するだけでログイン機能が動きます。
# urls.py
from django.contrib.auth.views import LoginView, LogoutView
from django.urls import path
urlpatterns = [
path('login/', LoginView.as_view(template_name='accounts/login.html'), name='login'),
path('logout/', LogoutView.as_view(), name='logout'),
]
テンプレートにはフォームを表示するだけです。
<!-- templates/accounts/login.html -->
{% extends "base.html" %}
{% block content %}
<h1>ログイン</h1>
{% if form.errors %}
<p>ユーザー名またはパスワードが正しくありません。</p>
{% endif %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">ログイン</button>
</form>
{% endblock %}ログイン成功後のリダイレクト先は settings.py で設定します。
# settings.py
LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/'
LOGIN_REDIRECT_URL はログイン成功後、LOGOUT_REDIRECT_URL はログアウト後のリダイレクト先です。URL にクエリパラメータ ?next=/articles/ が付いている場合は、そちらが優先されます。
ログアウトの実装
LogoutView は POST リクエストでログアウトを処理します。テンプレートにはボタンを置くだけです。
<form method="post" action="{% url 'logout' %}">
{% csrf_token %}
<button type="submit">ログアウト</button>
</form>GET リクエストでのログアウトはセキュリティ上推奨されません。リンクをクリックしただけで意図せずログアウトしてしまう可能性があるためです。Django 5.0 以降では GET によるログアウトがデフォルトで無効化されています。
テンプレートでの認証状態の判定
テンプレートでは user オブジェクトが自動的に利用可能です。is_authenticated でログイン済みかどうかを判定できます。
{% if user.is_authenticated %}
<p>{{ user.username }} さん、こんにちは。</p>
<form method="post" action="{% url 'logout' %}">
{% csrf_token %}
<button type="submit">ログアウト</button>
</form>
{% else %}
<a href="{% url 'login' %}">ログイン</a>
{% endif %}この user はコンテキストプロセッサ django.contrib.auth.context_processors.auth が自動で注入するもので、ビューで明示的に渡す必要はありません。
ビューでのアクセス制限
ログインしていないユーザーをページから弾くには、関数ビューなら @login_required デコレータ、クラスベースビューなら LoginRequiredMixin を使います。
from django.contrib.auth.decorators import login_required
@login_required
def dashboard(request):
return render(request, 'dashboard.html')
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import TemplateView
class DashboardView(LoginRequiredMixin, TemplateView):
template_name = 'dashboard.html'
未ログインのユーザーがアクセスすると、自動的にログインページにリダイレクトされます。リダイレクト先の URL は settings.py の LOGIN_URL で変更できます。
関数ビューに適用するデコレータ。シンプルで直感的
クラスベースビューに適用する Mixin。継承リストの最初に書く
authenticate と login を使った手動認証
LoginView を使わず、ビューの中で認証処理を自分で書くこともできます。
from django.contrib.auth import authenticate, login
def my_login(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('/')
else:
return render(request, 'accounts/login.html', {
'error': '認証に失敗しました。'
})
return render(request, 'accounts/login.html')
authenticate はユーザー名とパスワードを検証し、正しければユーザーオブジェクトを返します。login はセッションにユーザー情報を書き込み、以降のリクエストでそのユーザーとして認識されるようにします。
ほとんどの場合は LoginView で十分ですが、ログイン後の処理をカスタマイズしたい場合(ログ記録やリダイレクト先の動的切り替えなど)は手動認証が選択肢になります。
ユーザー作成
管理用のスーパーユーザーは createsuperuser コマンドで作成します。
python manage.py createsuperuserアプリケーション内でユーザーを作成する場合は create_user メソッドを使います。パスワードを自動的にハッシュ化してくれるため、生のパスワードがデータベースに保存されることはありません。
from django.contrib.auth.models import User
user = User.objects.create_user(
username='alice',
email='alice@example.com',
password='secure_password'
)
Django の認証システムは、セッション管理・パスワードのハッシュ化・CSRF 対策と連携して動作しています。個別の仕組みを意識しなくても安全な認証が実現できるのは、フレームワークとして認証が統合されている Django の大きな強みです。