0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Django 6.1 で AbstractBaseUser を継承しない User モデルに get_session_auth_hash() が必須になった

0
Last updated at Posted at 2026-09-15

Django 6.0から6.1へアップデートしたときに躓いたのでその備忘録になります。

TL;DR

  • Django 6.1 で auth.login() が user.get_session_auth_hash() を無条件で呼ぶようになりました
  • 解決策としてAbstractBaseUser の 3 メソッドを移植する必要があります

問題

Django 6.0 → 6.1 に上げたら、ログインを伴う処理が全てこのエラーで落ちました。

AttributeError: 'User' object has no attribute 'get_session_auth_hash'

原因

django/contrib/auth/__init__.py の login() にあった hasattr ガードが 6.1 で消えました。

# Django 6.0
session_auth_hash = ""
# RemovedInDjango61Warning.
if hasattr(user, "get_session_auth_hash"):
    session_auth_hash = user.get_session_auth_hash()

# Django 6.1
session_auth_hash = user.get_session_auth_hash()

AbstractBaseUser を継承していれば元から実装済みなので無関係ですが、継承せずに is_authenticated や check_password() を手で生やしている独自 User モデルは影響を受けるので次節の解決策対応が必要となります。

解決策

AbstractBaseUser の実装を、自分のパスワード列に合わせて移植します。
下記はあくまで一例です。

from django.conf import settings
from django.utils.crypto import salted_hmac


class User(models.Model):
    password_hash = models.CharField(max_length=255)  # 独自のパスワード列

    def get_session_auth_hash(self):
        return self._get_session_auth_hash()

    def get_session_auth_fallback_hash(self):
        for fallback_secret in settings.SECRET_KEY_FALLBACKS:
            yield self._get_session_auth_hash(secret=fallback_secret)

    def _get_session_auth_hash(self, secret=None):
        key_salt = "myapp.models.User.get_session_auth_hash"
        return salted_hmac(
            key_salt,
            self.password_hash,
            secret=secret,
            algorithm="sha256",
        ).hexdigest()

上記3メソッドがauth.login()時に実行されるので実装しましょう。

  • get_session_auth_fallback_hash() も必要です。get_user() がハッシュ検証失敗時に無条件で呼ぶためです
  • key_salt は AbstractBaseUser と別の文字列にしておきます (将来 AbstractBaseUser に移行したときハッシュが偶然一致しないように)

注意点

既存セッション失効による強制ログアウト

get_session_auth_hash() を実装すると、既存セッションが全て失効するのでログインしているユーザが一同にログアウトします。既存セッションにはハッシュが空文字で保存されているため、検証に失敗して session.flush() されます。つまりデプロイ直後に全利用者が強制ログアウトされ、再ログインが必要になります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?