Django でのユーザ認証

revision-up-to:17812 (1.4)

Django にはユーザ認証システムがついてきます。 Django のユーザ認証システムは、 ユーザアカウント、グループ、パーミッションとクッキーベースのユーザセッショ ンを扱えます。このドキュメントでは、ユーザ認証の仕組みについて説明します。

概要

認証システムは以下の要素から成り立っています:

  • ユーザ (Users)
  • パーミッション: あるユーザが特定のタスクを実行してよいかどうかを決め る、バイナリ (yes/no) のフラグです。
  • グループ (Groups): 複数のユーザに対してラベル付したり、認証を設定した りするための一般的な方法です。
  • メッセージ (Messages): 指定のユーザ(達) に対するメッセージをキューす るための簡単な方法です。

インストール

認証のサポートは Django アプリケーションとして django.contrib.auth にバ ンドルされています。インストールするには、以下のようにします:

  1. INSTALLED_APPS 設定に 'django.contrib.auth' と、 'django.contrib.contenttypes' を加えます。 (django.contrib.auth モジュールのモデル Permissiondjango.contrib.contenttypes に依存します)
  2. manage.py syncdb を実行します。

django-admin.py startproject が生成するデフォルトの settings.py ファイルの INSTALLED_APPS には、簡便のため 'django.contrib.auth' が最初から入っています。この場合は、単に manage.py syncdb するだけでかまいません。 このコマンドはその都度必要なものだけをインストールするので、 何度実行してもかまいません。

syncdb コマンドは必要なデータベーステーブルを作成し、インストー ル済みのアプリケーションで必要な全てのパーミッションオブジェクトを作成しま す。また、最初に実行したときには、ユーザにスーパユーザアカウントを作成する よう促します。

これだけで、認証サポートを使えるようになります。

ユーザ (User)

class models.User

API リファレンス

フィールド

class models.User

User オブジェクトには以下のフィー ルドがあります:

username

必須です。30 文字以下の文字列で、英数字 (アルファベット、数字、アン ダースコア) だけを使えます。

ユーザネームには今では @, +, . and - 等の文字列を 含めることが出来ます。
first_name

オプションです。30 文字以下です。オプションです。30 文字以下です。

last_name

オプションです。 30 文字以下です。

email

オプションです。 Email アドレスです。

password

必須です。パスワードのメタデータであるハッシュ値です (Django では生 のパスワードを保存しません)。生のパスワードは任意の長さでよく、どん な文字が入っていても構いません。詳しくは以下の「パスワード」の節を 参照して下さい。

is_staff

Bool 値です。この値が真なら、ユーザは admin サイトにアクセスできま す。

is_active

Bool 値です。この値が真なら、このアカウントを使ってログインできます。 アカウントを削除する代わりに、この値を False に設定してください。 もしアプリケーションが外部キーをユーザに対して持っていたとしても、 この方法なら破綻しないのでおすすめです。

ユーザがログインできるかどうかをコントロールする必要性がない場合でも 認証バックエンドが is_active フラッグをチェックする必要がない時 であっても、もしログインできるかどうかを is_activeFalse にしたくない場合でも、ログインビューの中ではあなた次第です。 しかしながら、 login() によって使わ れる AuthenticationForm ビューは does このチェックを実行します。has_perm() のよう な権限を確かめるメソッドのように、そして Django アドミンでの認証と 同じように。これらのような関数/メソッドはアクティブでないユーザに 対して、 False を返します.

is_superuser

Bool 値です。この値が真なら、ユーザは明示的な指定がなくても全てのパー ミッションを得ます。

last_login

ユーザが最後にログインした時刻を表す datetime オブジェクトです。デ フォルトではログイン時現在の日付/時刻になります。

date_joined

アカウントの作成された時刻を表す datetime オブジェクトです。デフォ ルトではアカウント作成時現在の日付/時刻になります。

メソッド

class models.User

User オブジェクトには groupsuser_permissions という二つの多対多のフィールドがあります。この 関係性のために、 User オブジェクト は他の Django モデル と同じようにして、関連づ けされたオブジェクトにアクセスできます:

myuser.groups = [group_list]
myuser.groups.add(group, group, ...)
myuser.groups.remove(group, group, ...)
myuser.groups.clear()
myuser.user_permissions = [permission_list]
myuser.user_permissions.add(permission, permission, ...)
myuser.user_permissions.remove(permission, permission, ...)
myuser.user_permissions.clear()

自動的に生成されるこれらの API に加え、 User オブジェクトには以下のカス タムメソッドがあります:

is_anonymous()

常に False を返します。 User オブジェクトを AnonymousUser オブジェクトと 区別する手段の一つです。 通常は、 is_authenticated() メソッ ドを使うようにしてください。

is_authenticated()

常に True を返します。ユーザを認証済みかどうかを調べる一つの方 法です。このメソッドの戻り値は、ユーザが正しいパーミッションを持っ ているか、あるいはアクティブなユーザであるかどうかに関係なく、ユー ザが正しいユーザ名とパスワードを入力したことだけを示します。

get_full_name()

first_namelast_name をスペースでつな げた文字列を返します。

set_password(raw_password)

渡された文字列をハッシュ化し、ユーザのパスワードに設定します。 User オブジェクトの保存は行い ません。

check_password(raw_password)

渡された文字列がこのユーザの正しい文字列ならば True を返します。 (このメソッドは比較時にパスワードのハッシュ処理を行います)

set_unusable_password()

ユーザにパスワード未設定のマークをつけます。パスワード未設定の状態 は、パスワードが空の文字列である状態と区別されます。パスワード未設 定状態のユーザに対して check_password() を呼び出 すと、決して True を返しません。このメソッドは User オブジェクトを直接保存し ません。

この機能は、 LDAP ディレクトリのような外部の認証ソースを使ってアプ リケーションの認証を行いたい場合に必要です。

has_usable_password()

ユーザに対して set_unusable_password() を 呼び出し、パスワードが未設定状態であれば False を返します。

get_group_permissions(obj=None)

ユーザが自分の属するグループから得ているパーミッションを表す文字列 からなるリストを返します。

リリースノートを参照してください

もし obj が引数に渡されていれば、その種類のオブジェクトへ対する、 属するグループから得ているパーミッションしか返しません。

get_all_permissions(obj=None)

ユーザ自身のもつパーミッションと、ユーザの属するグループのパーミッ ションの両方からなるリストを返します。

リリースノートを参照してください

もし、 obj が引数に渡されていれば、その特有のオブジェクトに 対するユーザのパーミッションを返します。

has_perm(perm, obj=None)

ユーザが特定のパーミッションを持っている場合に True を返します。 パーミッション名 perm は "<application name>.<lowercased model name>" のような形式で表し ます。ユーザがアクティブでない場合、このメソッドは常に False を 返します。

リリースノートを参照してください

もし obj が引数に渡されていれば、このメソッドはモデルに対する パーミッションをチェックせず、引数のオブジェクトに対するものを チェックしようとします。

has_perms(perm_list, obj=None)

ユーザが perm_list 内のパーミッションのいずれかを持っている場合に True を返します。各々のパーミッション名は "<app label>.<permission codename>" のような形式で表します。 ユーザがアクティブでない場合、このメソッドは常に False を 返します。

リリースノートを参照してください

もし obj が引数で渡されていれば、このメソッドはモデルに対する 権限ではなく、引数のオブジェクトに対するものを調べます。

has_module_perms(package_name)

ユーザが指定した名前のパッケージ (アプリケーション) の何らかのパー ミッションを持っていれば True を返します。ユーザがアクティブで ない場合、このメソッドは常に False を返します。

email_user(subject, message, from_email=None)

ユーザにメールを送信します。 from_emailNone の場合、 Django は DEFAULT_FROM_EMAIL 設定を使います。

get_profile()

ユーザのサイト固有のプロファイル (site-specific profile) を返します。 プロファイルを使えないサイトでは django.contrib.auth.models.SiteProfileNotAvailable を送出し ます。もしくはユーザがプロファイルを持っていなければ django.core.exceptions.ObjectDoesNotExtis を送出します。 サイト固有のユーザプロファイルを定義するには、後述の 追加のユーザ情報の保存 を参照して下さい。

マネジャ関数

class models.UserManager

User モデルには、以下のヘルパ関数 を備えたマネジャがあります。

create_user(username, email=None, password=None)
email パラメータはオプションになりました。username パラメ ータは、空のものと有効でない値が出た時の ValueError を上げるものをチェックするのに使われています。

ユーザを生成して保存し、生成された User を返します。 username, email は、自動的に小文字に変更され、 password は指定した値にな り、 is_activeTrue に設定されます。

パスワードを指定しなかった場合、 set_unusable_password() を 呼び出します。

使い方は ユーザの作成 を参照してください。

make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789')

指定した長さのランダムなパスワードを生成して返します。パスワードに 使える文字は文字列で指定します。 allowed_chars のデフォルト値は、 ユーザが見間違いやすい以下の文字を除いてあります:

  • i, l, I, and 1 (lowercase letter i, lowercase letter L, uppercase letter i, and the number one)
  • o, O, and 0 (uppercase letter o, lowercase letter o, and zero)

基本的な使い方

ユーザの作成

ユーザを作成する一番基本的な方法は、オブジェクトマネージャの create_user() ヘルパー関数を 使う方法です:

>>> from django.contrib.auth.models import User
>>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')
>>>
# この操作で、User オブジェクト user を保存できるようになります。
# 他のフィールドを変更したければ、属性を変更します。
>>> user.is_staff = True
>>> user.save()

Django のアドミンサイトを使用するユーザを作ることも出来ます。アドミンサイトの URL を /admin/ にひも付けると思います、 “Add user” ページは /admin/auth/user/add/ にあります。また、アドミンのメインページ(インデ ックスページ)の “Auth” セクションの “Users” へのリンクでも確認できます。 “Add user” 管理ページは、通常の管理ページ(アドミン)とはユーザネームと パスワードを、残りのフィールドを変更する前に埋めなくてはならない点で異なって います。

また、 note: もし、自身のユーザアカウントを Django のアドミンサイトを使える ようにしたいのならば、パーミッションを2つ与える必要があり、それぞれ ユーザを加える権限 ユーザを変更する権限です。(すなわち、 “Add user” と “Change user” の権限です。)もし、あなたのアカウントが 「ユーザを加える権限」は持っていても、「ユーザを変更する権限」を持っていない 場合、ユーザを加えることはできません。なぜか? それは、ユーザを加える権限を 有しているということは、スーパユーザを作る権限を有しているということで、 スーパーユーザは同様に、他のユーザを変えることができます。だから、 Django はそれに加えてユーザ変更の権限も、セキュリティ対策として 必要としているのです。

パスワードの変更

manage.py changepassword コマンドが追加されました。

manage.py changepassword *username* はコマンドラインからユーザのパスワードを変更する手続きを提供していま す。パスワードを変更するには、二度指定したユーザの変更後のパスワード を入力しなくてはいけません。二つがマッチすると、ただちにパスワードが 変更されます。ユーザを渡さないと、コマンドは最新のユーザのパスワード を変更しようとします。

パスワードの変更には set_password() を使います:

.. code-block:: python
>>> from django.contrib.auth.models import User
>>> u = User.objects.get(username__exact='john')
>>> u.set_password('new password')
>>> u.save()

特別な意図のない限り、 password 属性を直接設定しないでください。これについては次節で説明します。

Django はどのようにパスワードを保持するか

Django 1.4 では新しくフレキシブルなパスワードのストレージシステムと PBKDF2 をデフォルトで使用しています。以前のバージョンの Django では SHA1 が使われており、他のアルゴリズムを使用することは出来ませんでした。

User オブジェクトの password フィールドは、以下の形式:

algorithm$hash

すなわちストレージアルゴリズム(storage algorithm)と、ハッシュソルト (salt)、 そしてハッシュ値(hash) はドル記号 ("$") で分割した文字列形式をとります。 アルゴリズムはいくつかのハッシュ化または Django で使えるパスワードの ストレージ方式のうちの一つです。下を見てください。ハッシュ値はハッシュ関数の 結果であります。

通常では、 Django は PBKDF2 アルゴリズムをSHA256ハッシュ関数で暗号化します。 パスワードのストレッチ機構は NIST によって勧告されています。これはほとんどの ユーザにとっては満足できるものでしょう。高い安全性で、パスワードを破るには 莫大な計算量を必要とします。

しかしながら必要に応じて、他のアルゴリズムを選択することもあるでしょう、また 必要なセキュリティの度合いに応じてカスタムアルゴリズムを使用する必要もあるこ とでしょう。繰り返すと、ほとんどのユーザはそれを必要とはしていません。もし、 必要性が確かではないなら、それは必要なことではないでしょう。もし、あなたが そうしたいのならば読み進めてください。

Django では PASSWORD_HASHERS の設定でアルゴリズムを選択することが できます。これは Django で使用するハッシュ化のアルゴリズムクラス群のリストです、 リストの最初の項目(すなわち settings.PASSWORD_HASHERS[0] )はパスワードを 保存するために使われます。そして、他の項目は有効となったハッシュで実在する パスワードをチェックするために使われます。つまり、もし違うアルゴリズムを使用 したくなったときに、 PASSWORD_HASHERS を修正する必要があり、 リストの先頭に好きなアルゴリズムを組み込んでください。

通常 PASSWORD_HASHERS

PASSWORD_HASHERS = (
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
    'django.contrib.auth.hashers.BCryptPasswordHasher',
    'django.contrib.auth.hashers.SHA1PasswordHasher',
    'django.contrib.auth.hashers.MD5PasswordHasher',
    'django.contrib.auth.hashers.CryptPasswordHasher',
)

これは、 Django は PBKDF2 を全てのパスワードの保存時に使おうとする ということです。でも、保存されたパスワードをチェックする際には、 PBKDF2SHA1, bcrypt, SHA1, その他を用います。次以降のセクションでは 高度なユーザのために、設定を変更する一般的な二つの方法を紹介します。

bcrypt を Django で使うには

Bcrypt は一般的なパスワードの保存アルゴリズムは長期間パスワードを 保持しておくためにデザインされたアルゴリズムです。 Django では デフォルトで使われていません。サードパーティのライブラリを必要とする からです。しかし、 bcrypt をサポートするにはちょびっとの労力で 使えるように Django は配慮してくれています。

Bcrypt をデフォルトのアルゴリズムで使うには、以下に従ってください。

  1. py-bcrypt ライブラリをインストールしてください( sudo pip install py-bcrypt を実行するか、ライブラリを ダウンロードして、 python setup.py install を使って インストールしてください。)

  2. PASSWORD_HASHERS を設定してください。リスト内で BCryptPasswordHasher を先頭へ。セッティングファイルは こうなります:

    PASSWORD_HASHERS = (
         'django.contrib.auth.hashers.BCryptPasswordHasher',
         'django.contrib.auth.hashers.PBKDF2PasswordHasher',
         'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
         'django.contrib.auth.hashers.SHA1PasswordHasher',
         'django.contrib.auth.hashers.MD5PasswordHasher',
         'django.contrib.auth.hashers.CryptPasswordHasher',
     )
    

    (リストの中の他の項目は、そのままにしておいてください、または Django がパスワードをアップグレードできないようにしてください。 下部を見てください)

今、Django は Bcrypt をデフォルトの パスワード保存アルゴリズムとして使おうとします。

bcrypt を使う他の方法

Django 内で bcrypt を用いる方法はいくつかあります。 Django の bcrypt サポート同士では直接的に互換性がありません。 アップグレードするために、フォームの bcrypt$(生の bcrypt アウトプット)内で、データベースのハッシュを修正する必要が あります。例えば: `bcrypt$$2a$12$NT0I31Sa7ihGEWpka9ASYrEFkhuTNeBQ2xfZskIiiJeyFXhRgS.Sy

作業面の向上

PDKDF2 と、 bcrypt アルゴリズムは、沢山のイテレーションとハッシュの循環を 用います。これはシステムへの攻撃の手を遅めます。ハッシュ化された パスワードによって攻撃に立ち向かいます。しかし、コンピュータのマシンパワー の向上とともに、必要なイテレーションの数も増加しました。それ相当なものを 選んでいます( Django のリリースの度に数を増やしてます)が、その強度を 増したい時もあれば減らしたい時もあるでしょう、セキュリティ環境に応じて、 または実行環境に応じて。そうするために、サブクラスを作り適切なアルゴリズム と iterations パラメータの上書きをするでしょう。たとえば、イテレーション の回数を PBKDF2 で増加させるには:

  1. サブクラスを django.contrib.auth.hashers.PBKDF2PasswordHasher という 名前で作ります。:

    from django.contrib.auth.hashers import PBKDF2PasswordHasher
    
    class MyPBKDF2PasswordHasher(PBKDF2PasswordHasher):
        """
        PBKDF2PasswordHasher のサブクラスで百回以上イテレーションします
        """
        iterations = PBKDF2PasswordHasher.iterations * 100
    

    プロジェクトのどこかでこれを保存してください。例えば、 myproject/hashers.py のようなファイルを置くのがよいでしょう。

2. PASSWORD_HASHERS の中の最初の項目として新しいハッシュを加え ます:

PASSWORD_HASHERS = (
    'myproject.hashers.MyPBKDF2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
    'django.contrib.auth.hashers.BCryptPasswordHasher',
    'django.contrib.auth.hashers.SHA1PasswordHasher',
    'django.contrib.auth.hashers.MD5PasswordHasher',
    'django.contrib.auth.hashers.CryptPasswordHasher',
)

これだけで – Django は PBKDF2 を使ってパスワードを保存する時に、もっと 沢山のイテレーションを用いれるようになりました。

パスワードのアップグレード

ログインする時に、パスワードがアルゴリズムよりも好ましいもので保存されて いれば、 Django は自動的にアルゴリズムをそちらにアップグレードします。 この意味は、古い Django でもユーザがログインするたびにセキュアなものに なるということです、そしてまた新しく(そしてより良い)パスワードの 保持アルゴリズムが作られるたびにそちらへ切り替えられるということです。

しかしながら、 Django がアップグレードできるパスワードはアルゴリズムとして PASSWORD_HASHERS のなかで宣言されているものだけです。新しい システムにアップグレードする時には、 以前使っていたものを削除しない こと を気をつけてください。もし削除してしまうと、消去してしまったアルゴリズムを いつまでもアップグレードできないでいることになります。

匿名ユーザ (Anonymous users)

class models.AnonymousUser

django.contrib.auth.models.AnonymousUserdjango.contrib.auth.models.User と同じインタフェースを実装した クラスですが、以下の点で User と異 なります:

おそらく、実践上意識して AnonymousUser オブジェクトを使う必要はないはずです。とはいえ、匿名ユーザは次節で述べるよ うな形で Web リクエストで使われています。

スーパユーザの作成

INSTALLED_APPS'django.contrib.auth' を追加した直後に manage.py syncdb を実行すると、スーパユーザの作成を促す プロンプトを表示します。後でスーパユーザを作成したい場合には、以下のように コマンドラインユーティリティを使います:

manage.py createsuperuser --username=joe --email=joe@example.com

ユーティリティはパスワードの入力を促します。入力すると、ユーザは即座に作成 されます。 --username--email オプションを省 略すると、ユーティリティはそれらの値を入力するよう促します。

古い Django も使っている場合、以前からあるコマンドラインのスーパユーザ作成 方法も使えます:

python /path/to/django/contrib/auth/create_superuser.py

/path/to/ は自分のシステムの Django コードベースへのパスに応じて読 み変えて下さい。 manage.py は自動的に正しいパスと環境変数を決定するので、 manage.py を使うよう推奨します。

追加のユーザ情報の保存

ユーザに追加の情報をひもづけて保存したい場合のために、 Django ではサイトご とにユーザに関連付けられた「ユーザプロファイル」を取り出すためのメソッドを 提供しています。

ユーザプロファイルを利用するには、まず、ユーザにひもづけて保存したい情報を 入れるためのフィールドや持たせたいメソッド、そして User モデルへの user という名前で OneToOneField を持ったモデルを定義します。 OneToOneField には User に対してユーザごとにモデルが一つだけ生成 されるようにします。例をあげると:

from django.contrib.auth.models import User

class UserProfile(models.Model):
    # このフィールドが必要です.
    user = models.OneToOneField(User)

    # 他のフィールドはこちらにあります
    accepted_eula = models.BooleanField()
    facorite_animal = models.CharField(max_length=20, default="Dragons.")

このモデルをあるサイトのユーザプロファイルモデルにするには、 AUTH_PROFILE_MODULE に以下の内容をドット区切りの文字列で指定しま す:

  1. ユーザプロファイルモデルを定義している (小文字に変換した) アプリケーショ ン名 (別の言い方をするなら、 manage.py startapp で アプリケーションを作成するときに指定する名前を全て小文字にしたもの)。
  2. (小文字に変換した) モデルクラス名

例えば、プロファイルモデルが UserProfile という名前のクラスで、 accounts というアプリケーションで定義されているなら、設定値は以下のよう になるでしょう:

AUTH_PROFILE_MODULE = 'accounts.UserProfile'

ユーザプロファイルモデルが定義されていて、この規則通りになっていた場合、 User のオブジェクトは、 get_profile() というメソッドを 持つでしょう。 – これは User ユーザ プロファイルモデルに関連づけられたインスタンスを返します。

get_profile() のメソッドは、 プロファイルを作る訳ではありません。もし存在しないものがあれば、 自身でユーザモデルの django.db.models.signals.post_save のハンドル のシグナルを登録する必要と、ハンドラーの中で、 createdTrue ならばユーザプロファイルと関連させて作るようにします:

# models.py の中で

from django.contrib.auth.models import User
from django.db.models.signals import post_save

# 上のユーザプロファイルの定義
# ...

def create_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)

post_save.connect(create_user_profile, sender=User)

See also

シグナル シグナルについての詳しい情報です。

Web リクエストに対する認証

ここまでのドキュメントは、認証関連のオブジェクトを操作するための低水準の API について扱ってきました。より高水準の API では、 Django はこれらの認証フ レームワークを リクエストオブジェクト シ ステム内にフックできます。

まず、 SessionMiddleware およ び AuthenticationMiddlewareMIDDLEWARE_CLASSES 設定に追加して、これらのミドルウェアをインス トールします。詳しくは セッションのドキュメント を参照してください。

ミドルウェアをインストールしたら、ビューから request.user にアクセスできるように なります。 request.user は現在ログイ ンしているユーザの User オブジェクトを 表します。ユーザがログインしていなければ、 request.userAnonymousUser のインスタンスになります (前節を参照してください)。ログインユーザと匿名ユーザは、 is_authenticated() で以下のように 区別できます:

if request.user.is_authenticated():
    # Do something for authenticated users.
else:
    # Do something for anonymous users.

ユーザをログインさせる

Django では、 django.contrib.auth の中で、 authenticate()login() という二つの関数を提供しています。

authenticate()

あるユーザ名とパスワードに対する認証を行うには、 authenticate() を使ってください。この関数 は二つのキーワード引数、 usernamepassword をとり、ユーザ名 に対してパスワードが有効であった場合に User オブジェクトを返します。パス ワードが無効だった場合には、 authenticate()None を返します。例 えば:

from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:
    if user.is_active:
        print "You provided a correct username and password!"
    else:
        print "Your account has been disabled!"
else:
    print "Your username and password were incorrect."
login()

ユーザをログインさせるには、ビューの中で login() を使ってください。この関数は HttpRequest オブジェクトと User オブジェクトを引数にとります。 login() は Django のセッションフレームワー クを使って、ユーザの ID をセッションに保存します。従って、上でも述べた ように、セッションミドルウェアをインストールしておかねばなりません。

ユーザがログインする時に、匿名ユーザだった時のデータセットを残しておく 方法にも触れておきます。

以下の例は authenticate()login() の使い方を示しています:

from django.contrib.auth import authenticate, login

def my_view(request):
    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(username=username, password=password)
    if user is not None:
        if user.is_active:
            login(request, user)
            # Redirect to a success page.
        else:
            # Return a 'disabled account' error message
    else:
        # Return an 'invalid login' error message.

authenticate() は最初に呼び出してください

ユーザを手動でログインさせる場合、 login() を呼び出す前に 必ず authenticate() を呼び出してください。 authenticate() は、 User オブジェクトに、そのユーザが 認証バックエンドによって正しく認証されたことを示す属性を付加します。 (詳しくは 認証バックエンドのドキュメント を参照してください) この情報が後でログインの処理で必要だからです。

ユーザのパスワードを手動で管理する

django.contrib.auth.hashers モジュールは関数セットを ハッシュ化したパスワードの作成と有効化のために提供しています。 独立してそれらを使うことが出来ます。
check_password()
リリースノートを参照してください

ユーザ認証を手動で行うために平文パスワードとデータベース上のハッシュ化 パスワードを比較したい場合には、 django.contrib.auth.hashers.check_password() という便宜関数を使えます。この関数は、調べたい平文パスワードと、比較対 象のデータベースに格納されているユーザの password フィールド全体の 二つの引数をとり、二つが一致すれば True を、そうでなければ False を返します。

make_password()
リリースノートを参照してください

アプリケーションの中で使うフォーマット通りにハッシュ化したパスワードを作り るには、二つの引数をとります: ハッシュ化するアルゴリズムとプレーンテキスト のパスワードです。今サポートされているアルゴリズムは : 'sha1', 'md5' で、もし crypt のライブラリがインストールされ ていれば、それも使えます。もし、二つ目の引数が None だと、使えない パスワードがかえってきます(一つは、 django.contrib.auth.hashers.check_password() によって受け付けられ ません)

is_password_usable()
リリースノートを参照してください

与えられた文字列がハッシュ化されたパスワードであれば、それをチェックしま す。 django.contrib.auth.hashers.check_password() に反しないかが 確かめられます。

ユーザをログアウトさせる

logout()

django.contrib.auth.login() でログインしたユーザをログアウトさ せるには、ビューの中で django.contrib.auth.logout() を使ってください。この関数は、 HttpRequest オブジェクトを引数に取り、戻り値を持 ちません。例を以下に示します:

from django.contrib.auth import logout

def logout_view(request):
    logout(request)
    # Redirect to a success page.

ユーザがログインしていなくても logout() は エラーを送出しないことに注意してください。

logout() を呼び出すと、現在のリクエストに 結び付いたセッションデータを全て抹消します。その時に記憶されていたデー タは全て除去されます。これは、他のユーザが同じブラウザを使ってログイン し、直前にブラウザを使っていたユーザのセッションデータを読み出したりで きないようにするためです。ユーザのログアウト後に何らかのセッションデー タを記憶させたければ、 django.contrib.auth.logout()後で 行ってください。

ログインとログアウトのサイン

リリースノートを参照してください

auth 認証のフレームワークは二つ signals を使います。それは、ユーザがログインまたはログアウトした時のお知らせ のためです。

django.contrib.auth.signals.user_logged_in

ユーザがログインに成功した時に送信します。

このシグナルが引数で送られます:

sender
上にある通り: このクラスはユーザがログインした時のものです
request
最新のものは HttpRequest のインスタンスです。
user
ログインしたユーザのインスタンスです。
django.contrib.auth.signals.user_logged_out

ユーザがログアウトする時に送信するものは

sender
上にあるとおり: ログアウトしたユーザのクラスまたは ユーザが認証されていなければ None を返します。
request
最新のものは HttpRequest instance.
user
ログアウトしたユーザのインスタンスか、もし認証されていな ければ None を返します。

ログインユーザだけがアクセスできるように制限をかける

生真面目な方法

ページへのアクセスを制限する単純で生真面目な方法は、 request.user.is_authenticated() をチェックして、ログインページにリダイレクトするというものです:

from django.http import HttpResponseRedirect

def my_view(request):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/login/?next=%s' % request.path)
    # ...

あるいは、エラーメッセージを出しても構いません:

def my_view(request):
    if not request.user.is_authenticated():
        return render_to_response('myapp/login_error.html')
    # ...

login_required デコレータ

decorators.login_required([redirect_field_name=REDIRECT_FIELD_NAME, login_url=None])

手間を省くために、 login_required() デコレータを使え ます:

from django.contrib.auth.decorators import login_required

@login_required
def my_view(request):
    ...

login_required() に従うと:

  • もし、ユーザがログインしていなければ、クエリ文字列の現在の完全 パスを通って、 settings.LOGIN_URL へとリダイレクトします。例えば: /accounts/login/?next=/polls/3/
  • もし、ユーザがログインしていれば、通常のビューを実行します。 ビューコードは、ユーザがログインしているかという仮定には縛られません。

通常、ユーザがリダイレクトされる認証が成功した場合のパスは クエリ文字列のパラメータの中に "next" という名前で保持されています。 もし、このパラメータに別の名前をあてがいたい場合には、 login_required() はオプションの redirect_field_name パラメタをとります。例えば:

from django.contrib.auth.decorators import login_required

@login_required(redirect_field_name='my_redirect_field')
def my_view(request):
    ...

もし、 redirect_field_name に値を設定した場合、ログインテンプレート もそれに応じて変更する必要があります、テンプレートのコンテキスト(context) 変数が保持するリダイレクトパスは redirect_field_name で設定した値を、 "next" (通常)のかわりにキーとして扱うからです。

リリースノートを参照してください

login_required() もまた、オプション として login_url パラメータを取ります。例えば:

from django.contrib.auth.decorators import login_required

@login_required(login_url='/accounts/login/')
def my_view(request):
    ...

login_url パラメータを設定しない場合には settings.LOGIN_URL に適切な Django のビュー関数 を対応づけておかねばなりません。例えば URLconf に以下のような行を設定します:

(r'^accounts/login/$', 'django.contrib.auth.views.login'),
views.login(request[, template_name, redirect_field_name, authentication_form])

URL name: login

the URL documentation に URL パターンについて 詳細にのっているので見てください。

django.contrib.auth.views.login は以下のような処理を行います:

  • GET で呼び出されると、同じ URL に対して POST を行うためのログ インフォームを表示します。これについては後でもう少し説明します。
  • POST で呼び出されると、ユーザのログイン処理を試みます。ログイ ンに成功すると、ビューは next に示された URL にリダイレクトし ます。 next を指定しない場合、 settings.LOGIN_REDIRECT_URL (デフォルト値は /accounts/profile/) にリダイレクトします。ロ グインに失敗すると、ログインフォームを再度表示します。

開発者は registration/login.html という名前のテンプレート上でログイ ンフォームを提供せねばなりません。 Django はこのテンプレートに、以下の 3 つのテンプレートコンテキスト変数を渡します:

  • form: ログインフォームを表現する Form オブジェクトです。 Form オブジェクトの詳細 は forms のドキュメント を参照してく ださい。
  • next: ログイン成功後にリダイレクトされる先の URL です。 URL にはクエリ文字列を含めてかまいません。
  • site: 現在の Site, SITE_ID のセッティングに従っています。もし、サイト フレームワークがインストールされていなければ、これは、 RequestSite のインスタンスが セットされます。これはサイトの名前とドメインを現在の HttpRequest から取ってきます。
  • site_name: site.name のための別名(alias)です。もし、 サイトフレームワークがインストールされていなければ、 request.META['SERVER_NAME'] の値がセットされます。サイトについてもっと知りたければ “sites” フレームワーク を見てください。

registration/login.html テンプレートを呼び出したくないのなら、 URLconf を通じて外部パラメタ template_name をビューに渡してください。 例えば、 myapp/login.html を使いたければ、URLconf の行は以下の ようになります:

(r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'myapp/login.html'}),

GET フィールドの名前を指定できます。 GET フィールドは、 redirect_field_name からビューへの、 ログイン後のリダイレクト先を含むURLを設定してください。 通常では、このフィールドは next です。

編集の雛型にできるような registration/login.html テンプレートの 例を以下に示します。このテンプレートは、 content ブロックの定義された base.html があるという前提で書かれています:

{% extends "base.html" %}
{% load url from future %}

{% block content %}

{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}

<form method="post" action="{% url 'django.contrib.auth.views.login'%}">
{% csrf_token %}
<table>
<tr>
    <td>{{ form.username.label_tag }}</td>
    <td>{{ form.username }}</td>
</tr>
<tr>
    <td>{{ form.password.label_tag }}</td>
    <td>{{ form.password }}</td>
</tr>
</table>

<input type="submit" value="login" />
<input type="hidden" name="next" value="{{ next }}" />
</form>

{% endblock %}
リリースノートを参照してください

もし、他の認証を使っているならば( 他の認証データソースを使う を見て ください)カスタムされた認証フォームを通って、 authentication_form パラメータを経てログインビューへと行きます。このフォームは request キーワード引数を自身の __init__ メソッドの中で受け取らなくては いけません。そして、 get_user メソッドは認証されたユーザーオブジェクト を返します。(このメソッドは、成功したフォームバリデーションの 後に一度だけ呼ばれます。)

リリースノートを参照してください

login() のビューと その他の組み込みビュー は今、 全て TemplateResponse のインスタンス を返します。これは、レスポンスデータをレンダリング前に容易に改変できる ようにします。もっと情報が欲しければ TemplateResponse documentation を見て ください。

その他の組み込みビュー

login() ビューに加えて、認証システムはその他の役に立つビューを django.contrib.auth.views: に持っています。:

logout(request[, next_page, template_name, redirect_field_name])

ユーザをログアウトさせます。

URL name: logout

URL のドキュメント を見てください。もっと 詳しく URL パターンを使う上での情報が載っています。

オプション引数:

  • next_page: ログアウト後にリダイレクトされる URL です。
  • template_name: ログアウトページのテンプレートの完全な名前です。 この引数を省略すると、デフォルト値の registration/logged_out.html を使います。
  • redirect_field_name: GET フィールドの名前で、ログアウト後の リダイレクト先 URL を含みます。 GET パラメータが渡されると next_page が上書きされます。

テンプレートコンテキスト:

  • title: “Logged out” の文字列を翻訳した値になります。
  • site: 現在の Site で、 SITE_ID のセッティングに従っています。もし、サイト フレームワークをインストールしていなければ、これは RequestSite のインスタンス がセットされ、サイトの名前てドメインを現在の HttpRequest から取ってきます。
  • site_name: site.name のための別名(alias)です。もし、 サイトフレームワークがインストールされていなければ、 request.META['SERVER_NAME'] の値がセットされます。サイトについてもっと知りたければ “sites” フレームワーク を見てください。
logout_then_login(request[, login_url])

ユーザをログアウトさせてから、ログインページにリダイレクトします。

オプション引数:

  • login_url: ログインページへのリダイレクト先です。この引数を省 略すると、デフォルト値の settings.LOGIN_URL を使います。
password_change(request[, template_name, post_change_redirect])

ユーザがパスワードを変更できるようにします。

オプション引数:

  • template_name: パスワード変更ページのテンプレートの完全な名前 です。この引数を省略すると、デフォルト値の registration/password_change_form.html を使います。

  • post_change_redirect: パスワードの変更に成功した場合の URLリダイレクト先です。

    リリースノートを参照してください
  • password_change_form: “パスワードの変更” フォームのカスタマイズ は、 user のキーワード引数を受け取らなくてはいけません。 フォームは実際にウーザのパスワードが変更される責任があります。 通常では、 PasswordChangeForm になります。

テンプレートコンテキスト:

  • form: パスワード変更のためのフォームです。
password_change_done(request[, template_name])

ユーザがパスワードを変更した後のページを表示するためのビューです。

URL name: password_change_done

オプション引数:

  • template_name: パスワード変更完了ページのテンプレートの完全な 名前です。この引数を省略すると、デフォルト値の registration/password_change_done.html を使います。
password_reset(request[, is_admin_site, template_name, email_template_name, password_reset_form, token_generator, post_reset_redirect, from_email])

ユーザがパスワードをリセットできるように、一回しか使用できないリンクを 作成します。また、新たなパスワードをメールで送信します。

from_email 引数が加えられました。
使えないパスワードでフラグ付けされたユーザ( set_unusable_password() を見てください)は、パスワードのリセットをリクエストできません。 外部の認証ソース、例えばLDAPのようなものを使う際の悪用を防ぐためです。

URL name: password_reset

オプション引数:

  • template_name: パスワードリセットページのテンプレートの完全な 名前です。この引数を省略すると、デフォルト値の registration/password_reset_form.html を使います。

  • email_template_name: 新しいパスワードを e-mail で送信する際に 使うテンプレートの完全な名前です。この引数を省略すると、デフォル ト値の registration/password_reset_email.html を使います。

  • subject_template_name: 新しいパスワードのemailを生成するのに使う テンプレートのフルネームです。デフォルトでは registration/password_reset_email.html が設定されています。

    リリースノートを参照してください
  • password_reset_form: パスワードのセットに使うフォームです。 デフォルトでは PasswordResetForm が設定されています。

  • token_generator: パスワードのチェックに使うクラスのインスタンスで す。通常は default_token_generator に設定されています、これは django.contrib.auth.tokens.PasswordResetTokenGenerator のインスタ ンスです。

  • post_reset_redirect: パスワードの変更が成功した後にリダイレクト する URL です。

  • from_email: 有効な email アドレスです。通常 Django が使うのは DEFAULT_FROM_EMAIL です。

テンプレートコンテキスト:

  • form: パスワードリセットのためのフォームです。 (上にある password_reset_form` を見てください)

Email テンプレートコンテキスト:

  • email : user.email の別名です。
  • user: 現在の User で、 email フォームフィールドに従っています。アクティブユーザのみ が、パスワードをリセットすることができます。( User.is_active is True )
  • site_name: sit.name のエイリアス(別名)です。もし、 インストール済みのサイトフレームワークがない場合は、 request.META['SERVER_NAME'] の値をセットします。これについては “sites” フレームワーク を ご覧ください。
  • domain: site.domain のエイリアス(別名)です。もし、 サイトフレームワークがインストールされていない場合、これは request.get_host() の値をセットします。
  • protocol: http or https
  • uid: ユーザのIDは36進数でエンコードされます。
  • token: トークンはパスワードが有効なものかをチェックします。

registration/password_reset_email.html ( email ボディテンプレー ト)にサンプルがあります:

{% load url from future %}
誰かがパスワードの変更を求めたら {{ email }} のように
email から送られたリンクへと飛ぶことになります。下のリンクに従ってください。:
{{ protocol }}://{{ site_name }}{% url 'auth_password_reset_confirm' uidb36=uid token=token %}

同じテンプレートコンテキストが、サブジェクトテンプレートに使われる 時、サブジェクトは一行のプレーンテキストでなくてはなりません。

views.password_reset_done(request[, template_name])

ユーザがパスワードをリセットした後のページを表示するためのビューです。 このビューは password_reset() ビューが post_reset_redirect の URL セットを所持していない時にデフォルトで呼ばれます。

オプション引数:

  • template_name: パスワードリセット完了ページのテンプレートの完 全な名前です。この引数を省略すると、デフォルト値の registration/password_reset_done.html を使います。
password_reset_confirm(request[, uidb36, token, template_name, token_generator, set_password_form, post_reset_redirect])

Presents a form for entering a new password.

オプション 引数:

  • uidb36: 36進数でエンコードされたユーザのIDです。デフォルトでは None です。
  • token: パスワードが有効かをチェックするためのトークンです。 デフォルトでは None です。
  • template_name: 確定したパスワードのビューを表示するテンプレート のフルネームです。
  • token_generator: パスワードをチェックするためのクラスのインスタ ンスです。これは default_token_generator がデフォルトです。 そして、 django.contrib.auth.tokens.PasswordResetTokenGenerator のインスタンスでもあります。
  • set_password_form: パスワードをセットするためのフォームとして 使用されます。 SetPasswordForm がデフォルトです。
  • post_reset_redirect: パスワードのリセットが終了した後に リダイレクトされる先です。デフォルトでは None です。

テンプレートコンテキスト:

  • form: 新しいユーザのパスワードをセットするための フォームです(上にある set_password_form を見てください)
  • validlink: Boolean 型です。 True でリンクが有効か( uidb36 とトークンの組み合わせ)またはまだ使われていないかです。
password_reset_complete(request[, template_name])

ユーザにパスワードの変更が成功したということを伝えるためのビューです。

URL name: password_reset_complete

オプション引数:

  • template_name: ビューを表示するためのテンプレートのフルネームで す。registration/password_reset_complete.html がデフォルトの 値になります。

ヘルパー関数

redirect_to_login(next[, login_url, redirect_field_name])

ログインページへリダイレクトします、ログインに成功したら、トップ画面で はなく、違う URL へと戻ります。

必要な 引数:

  • next: ログインに成功した後のリダイレクト先の URL です。

オプション 引数:

  • login_url: リダイレクトするログインページの URL です。 デフォルトでは settings.LOGIN_URL となります。
  • redirect_field_name: GET フィールドに含まれているログアウト後 にリダイレクトする先の URL です。 GET パラメータが渡されていれば next を上書きします。

組み込みフォーム

組み込みビューを使いたくないけれども、フォームクラスを書かずに済ませたい場 合のために、認証システムは組み込みのフォームを django.contrib.auth.forms でいくつか提供しています:

class AdminPasswordChangeForm

Admin インタフェースでユーザのパスワード変更に使われているフォームです。

class AuthenticationForm

ユーザをログインさせるためのフォームです。

class PasswordChangeForm

ユーザにパスワードを変更させるためのフォームです。

class PasswordResetForm

パスワードをリセットし、新たなパスワードを送信するためのフォームです。

class SetPasswordForm

古いパスワードを入力することなく、パスワードを変更させるための フォームです。

class UserChangeForm

ユーザ情報とパーミッションを変更するためのアドミンインターフェースです

class UserCreationForm

新たなユーザを作成するためのフォームです。

テストにパスしたログインユーザだけがアクセスできるように制限をかける

特定のパーミッションやその他のテストの結果に応じたアクセスの制限には、前節 で説明したの本質的に同じことをします。

一番簡単な方法は、ビュー内で直接 request.user に対するテストを実行す るというものです。例えば、以下のビューではユーザがログイン済みで、かつ polls.can_vote というパーミッションを持っているかチェックします:

def my_view(request):
    if not request.user.has_perm('polls.can_vote'):
        return HttpResponse("You can't vote in this poll.")
    # ...
user_passes_test(func[, login_url=None])

user_passes_test デコレータを使えば、手間を省けます:

from django.contrib.auth.decorators import user_passes_test

@user_passes_test(lamda u: u.has_perm('polls.can_vote'))
def my_view(request):
    ...

ここでは、簡単な例としてパーミッションのテストに user_passes_test() を使っています が、単にあるユーザがあるパーミッションを有しているかをテストしたいだけ なら、後で解説する django.contrib.auth.decorators.permission_required() デコレータ を使えます。

user_passes_test() には必須の引数 が一つあります。この引数は、 User を引数に取り、ユーザにページのビューを許可する場合には True を返す 呼び出し可能オブジェクトでなければなりません。 user_passes_test()User が匿名かどうかを自動的に調べ ないので注意してください。

user_passes_test() はオプション の引数として login_url をとります。この引数を使うとログインページへ の URL を指定できます (デフォルトでは settings.LOGIN_URL になります)。

例えば:

from django.contrib.auth.decorators import user_passes_test

@user_passes_test(lambda u: u.has_perm('polls.can_vote'), login_url='/login/')
def my_view(request):
    ...

permission_required デコレータ

decorators.permission_required([login_url=None, raise_exception=False)

あるユーザが特定のパーミッションを有しているかのチェックは、比較的よく ある操作なので、 Django はショートカットとして permission_required() という デコレータを用意しています。このデコレータを使うと、上の例は以下のよう に書き直せます:

from django.contrib.auth.decorators import permission_required

@permission_required('polls.can_vote')
def my_view(request):
    ...

As for the User.has_perm() method, permission names take the form "<app label>.<permission codename>" (すなわち polls.choice は は polls アプリケーションのモデルへのパーミッションです.)

permission_required() もまた、 login_url を引数に取れます。例えば:

from django.contrib.auth.decorators import permission_required

@permission_required('polls.can_vote', login_url='/loginpage/')
def my_view(request):
    ...

login_required デコレータと同様、 login_url のデフォルト値は settings.LOGIN_URL です。

リリースノートを参照してください

raise_exception パラメータが追加されました。もし、パラメータが 与えられると、でコレータは PermissionDenied を送出します。 the 403 (HTTP Forbidden) view を、ログインページへのリダイレクトの代わりに出します。

アクセスを汎用ビューに制限する

アクセスを 汎用ビュー に制限するには、 View.dispatch という クラスのメソッドをデコレートする必要があります。 クラスのデコレート の詳細を確認してください。

汎用ビューをベースにした関数

class-based generic view にアクセスを制限 するにはビューを囲む薄いラッパコードを書き、URLconf を変更して、 ジェネリックビュー自体ではなくラッパコードを指すようにします。例えば:

from django.views.generic.date_based import object_detail

@login_required
def limited_object_detail(*args, **kwargs):
    return object_detail(*args, **kwargs)

パーミッション (Permission)

Django には単純なパーミッション機構がついてきます。このパーミッション機構は 特定のユーザやユーザのグループに対してパーミッションを結びつける手段を提供 します。

パーミッション機構は Django の admin サイトでも使われていますが、自作のコー ド内でも自由に使えます。

  • “add” フォームをビューし、オブジェクトを追加するためのアクセスを、そ の型のオブジェクトの “add” パーミッションを持つユーザに制限しています。
  • 変更リストをビューし、”change” フォームをビューしてオブジェクトを変更 するためのアクセスを、その型のオブジェクトの “change” パーミッション を持つユーザに制限しています。
  • あるオブジェクトを削除するためのアクセスを、その型のオブジェクトの “delete” パーミッションを持つユーザに制限しています。

パーミッションはオブジェクトインスタンスごとではなく、オブジェクトの型ごと にグローバルに設定されます。例えば、「Mary はニュース記事を変更できる」のよ うには書けますが、現状では、「Mary はニュース記事を変更できる。ただし彼女が 書いた分だけ」とか、「Mary はある状態にある記事か、ある日時に出版されたか、 ある ID の記事だけを変更できる」のようには書けません。後者の機能については は、現在 Django の開発者達が議論中です。

デフォルトのパーミッション

INSTALLED_APPS 設定に django.contrib.auth を追加している場合、 インストールされている全てのアプリケーションのモデルについて、追加 (add)、 変更 (change)、および削除 (delete) というデフォルトのパーミッションが作成さ れます。

これらのパーミッションは、 manage.py syncdb を実行した ときに生成されます。厳密には、 django.contrib.authINSTALLED_APPS 設定に追加した直後に syncdb を実行する と、その時インストールされていた全てのアプリケーションと、新たに追加したア プリケーションのデフォルトパーミッションが作成されます。以後、 manage.py syncdb を実行するたびに、新たに追加されたモデ ルのデフォルトパーミッションが生成されます。

もし、アプリケーションを app_label foo という名前にしていてモデルの名前を Bar だと仮定します、 標準のパーミッションをテストするにはこのようにします:

  • add: user.has_perm('foo.add_bar')
  • change: user.has_perm('foo.change_bar')
  • delete: user.has_perm('foo.delete_bar')

カスタムのパーミッション

カスタムのパーミッションを生成するには、 permissions という モデルのメタ属性 を使います。

この例では、 Task モデルに三つのカスタムパーミッションを作っています、 すなわち Task インスタンスによってユーザが出来るアクションが決まります。 アプリケーション内でのコードは:

class Task(models.Model):
    ...
    class Meta:
        permissions = (
            ("view_task", "Can see available tasks"),
            ("change_task_status", "Can change the status of tasks"),
            ("close_task", "Can remove a task by setting its status as closed"),
        )

この定義の役割は特別なパーミッションを追加することだけです。 manage.py syncdb を実行すると、コードは パーミッションをチェックする役割を負います。それが実行されるのは、 ユーザがアプリケーションによって機能へとアクセスしようとする時 (タスクを見て、タスクのステータスを変え、タスクを閉じるような動作) です。上の例に続ければ、ユーザがタスクを見る時にそれと共にチェックし ます:

user.has_perm('app.view_task')

API リファレンス

class models.Permission

フィールド

Permission オブジェクトには以下のフィー ルドがあります:

Permission.name

必須です。50 文字以下です。例: 'Can vote'

Permission.content_type

必須です。インストール済みの Django モデルのレコードが入った django_content_type データベーステーブルへの参照です。

Permission.codename

必須です。 100 文字以下です。例: 'can_vote'

メソッド

Permission オブジェクトは、他の Django モデル と同じく、標準的なデータアクセスメソッ ドを備えています。

プログラム的にパーミッションを作る

Meta クラス内でカスタムパーミッションが定義される一方、 直接的にパーミッションを作ることもまたできます。例えば、 myappBlogPost モデルに対して、 can_publish パーミッションを作ろうとすると:

from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType

content_type = ContentType.objects.get(app_label='myapp', model='BlogPost')
permission = Permission.objects.create(codename='can_publish',
                                       name='Can Publish Posts',
                                       content_type=content_type)

パーミッションは自身のクラスの user_permissions アトリビュートか、 Grouppermissions アトリビュートから User へと割り当てることができます。

認証データのテンプレート上での扱い

RequestContext を使っている場合、ログイン ユーザとそのパーミッションに テンプレートコンテキスト (template context) を使っ てアクセスできます。

技術的な話題

デフォルトの設定では、テンプレートコンテキストに RequestContext を使うようになっていて、 かつ TEMPLATE_CONTEXT_PROCESSORS の設定に "django.contrib.auth.context_processors.auth" が入っています。この場合にのみ、 上記の変数をテンプレートコンテキストの中で使えるようになります。詳しくは RequestContext のドキュメント を参照してください。

ユーザ

現在のログインユーザは、 User インスタ ンスであっても AnonymousUser インスタ ンスであっても、テンプレート変数 {{ user }} に入ります:

{% if user.is_authenticated %}
    <p>Welcome, {{ user.username }}. Thanks for logging in.</p>
{% else %}
    <p>Welcome, new user. Please log in.</p>
{% endif %}

このテンプレートコンテキスト変数は、 RequestContext が使われていないと 使うことが出来ません。

パーミッション

現在のログインユーザのパーミッションはテンプレート変数 {{ perms }} に入っ ています。この変数はパーミッションオブジェクトをテンプレートで扱いやすくす るためのプロキシ (proxy) である、 django.contrib.auth.context_processors.PermWrapper のインスタンスです。

バージョン1.3の変更で、 django.contrib.auth.context_processors の中に PermWrapper が置かれました。

{{ perms }} オブジェクトに対して 1 段の属性参照を行うと、実際には User.has_module_perms へのプロキシになっています。例えば下記の例は、ログインユーザが foo とい うアプリケーションへのパーミッションを持っている場合に True を表示しま す:

{{ perms.foo }}

2 段階属性を探索すると、 User.has_perm へのプロキ シに到達します。以下の例では、ログインユーザが foo.can_vote へのパーミッ ションを持つ場合に True を表示します:

{{ perms.foo.can_vote }}

こうして、テンプレート内で {% if %} 文を使ってチェックを行えます:

{% if perms.foo %}
    <p>You have permission to do something in the foo app.</p>
    {% if perms.foo.can_vote %}
        <p>You can vote!</p>
    {% endif %}
    {% if perms.foo.can_drive %}
        <p>You can drive!</p>
    {% endif %}
{% else %}
    <p>You don't have permission to do anything in the foo app.</p>
{% endif %}

グループ (Group)

グループは、パーミッションを適用するユーザのカテゴリを作ったり、一連のユー ザに何らかのラベルを適用するための汎用的な手段です。一人のユーザは複数のグ ループに所属できます。

グループに所属したユーザは、そのグループに許可されているパーミッションを自 動的に得ます。例えば、 Site editors というグループに can_edit_home_page というパーミッションをがあれば、そのグループに属する ユーザはみな, can_edit_home_page のパーミッションを持ちます。

パーミッションだけではなく、グループはユーザをカテゴリに分けてラベルを付け たり、機能を拡張したりできます。例えば、 '特別なユーザ' のグループを作 成して、そのグループのユーザ向けに、例えばサイト内のメンバー限定エリアへの アクセスを提供したり、メンバーだけに email メッセージを送るといった、特別 な処理を行うコードを書けます。

メッセージ (Message)

API リファレンス

class models.Group

フィールド

Group オブジェクトはそれに続くフィールドを 持っています:

Group.name

必須です。 80文字以下です。どんな文字でも使えます。例えば: 'Awesome Users' このように。

Group.permissions

Many-to-many フィールド Permissions:

group.permissions = [permission_list]
group.permissions.add(permission, permission, ...)
group.permissions.remove(permission, permission, ...)
group.permissions.clear()

他の認証データソースを使う

ほとんどのケースでは、 Django についてくる認証メカニズムで十分のはずですが、 場合によっては別の認証データソース (authentication source) をフックしたい、 すなわち、Django 外のユーザ名やパスワードデータや認証メソッドを使いたいよう なケースもあることでしょう。

例えば、会社が LDAP 構成を使って社員のユーザ名やパスワードを管理していると しましょう。ネットワーク管理者にとっても、またユーザ自身にとっても、 LDAP とDjango ベースのアプリケーションの双方で別々のアカウントを維持するのはいさ さか骨の折れる作業です。

こうした状況を扱うために、 Django の認証システムは別の認証ソースをプラグイ ンできるようになっています。 Django がデフォルトで使っているデータベースの スキームをオーバライドしたり、デフォルトのシステムを他のシステムと並列して 動作させたりできます。

authentication backend reference を見てください。 もっと詳しい情報が載っています。

他の認証バックエンドを指定する

舞台裏では、 Django は認証に使う「認証バックエンド」のリストを維持していま す。前述の 「ユーザをログインさせる」 で説明したように django.contrib.auth.authenticate() を呼び出すと、Django は全ての認 証バックエンドにわたって認証テストを試みます。最初の認証メソッドに失敗する と次の認証バックエンド、という具合にして、認証に成功しない限り、全てのバッ クエンドを試すまで続けます。

認証に使うバックエンドのリストは AUTHENTICATION_BACKENDS 設定に 指定します。この値は Python モジュールパス名からなるタプルで、認証方法を実 装したクラスの名前を指定します。認証クラスは Python パス上のどこにあっても かまいません。

デフォルトでは、 AUTHENTICATION_BACKENDS の値は:

('django.contrib.auth.backends.ModelBackend',)

に設定されています。このクラスは、 Django のユーザデータベースをチェックす る認証スキームです。

AUTHENTICATION_BACKENDS の順番には意味があり、同じユーザ名とパス ワードが複数のバックエンドで有効な値であったとしても、 Django は最初にユー ザ名とパスワードがマッチした時点で認証処理を停止します。

Note

一度ユーザが認証されると、 Django はユーザのセッション内でどのバック エンドによってユーザが認証されたかを保持します。そして、同じバックエンド を「認証されたユーザ」であることが必要とされる時にアクセスします。 この効率性が意味するのは、認証ソースが一回のセッションを基礎として キャッシュされるということです。だから、もし AUTHENTICATION_BACKENDS を変更すると、セッションデータをクリア しなければ、異なる方法で再認証することができません。これのシンプルな方法 は、 Session.objects.all().delete() を実行することです。

認証バックエンドを作成する

認証バックエンドの実体は、 get_user(user_id)authenticate(**credentials) という二つのメソッドを実装したクラスです。

get_user メソッドはユーザ名、データベース ID などを表す引数 user_id をとり、対応する User オブジェクトを返します。

authenticate メソッドは証明情報、すなわちユーザ名とパスワードなどをキー ワード引数の形で受け取ります。ほとんどの場合、以下のような形式をとります:

class MyBackend(object):
    def authenticate(self, username=None, password=None):
        # Check the username/password and return a User.

以下のようにトークンに対する認証を行うようにも書けます:

class MyBackend(object):
    def authenticate(self, token=None):
        # Check the token and return a User.

どちらの方法でも、 authenticate は受け取った証明情報をチェックし、証明 情報が有効な場合、対応する User オブジェクトを返さねばなりません。証明 情報が無効なら、 None を返します。

Django の admin システムは、冒頭で説明した Django の User オブジェクト と強くカップリングしています。従って、今のところ自作の認証バックエンドを扱 うには、 (LDAP ディレクトリや外部の SQL データベースなどのような) 別のバッ クエンド上のユーザに対して Django の User オブジェクトを生成するのがベ ストです。あらかじめスクリプトを書いておいてもよいですし、ユーザが最初にロ グインした際に、 authenticate メソッドでその処理を行うようにしてもよい でしょう。

以下に示すバックエンドの例では、 settings.py ファイルに定義されたユーザ 名とパスワードに対して認証を行い、ユーザが最初に認証を行ったときに User オブジェクトを生成します:

from django.conf import settings
from django.contrib.auth.models import User, check_password

class SettingsBackend(object):
    """
    セッティングにそぐわない認証の ADMIN_LOGIN and ADMIN_PASSWORD

    ログインネームとパスワードのハッシュを使ってみます。例えば:

    ADMIN_LOGIN = 'admin'
    ADMIN_PASSWORD = 'sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de'
    """

    supports_inactive_user = False

    def authenticate(self, username=None, password=None):
        login_valid = (settings.ADMIN_LOGIN == username)
        pwd_valid = check_password(password, settings.ADMIN_PASSWORD)
        if login_valid and pwd_valid:
            try:
                user = User.objects.get(username=username)
            except User.DoesNotExist:
                # Create a new user. Note that we can set password
                # to anything, because it won't be checked; the password
                # from settings.py will.
                user = User(username=username, password='get from settings.py')
                user.is_staff = True
                user.is_superuser = True
                user.save()
            return user
        return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

カスタムのバックエンドでパーミッションを扱う

カスタムの認証バックエンドから、独自のパーミッションを提供できます。

認証バックエンドがパーミッション照会のための関数 (get_group_permissions(), get_all_permissions(), has_perm(), および has_module_perms()) をサポートして いる場合、ユーザモデルはパーミッションの照会をバックエンドに移譲します。

あるユーザに付与されるパーミッションの集合は、全てのバックエンドの返しうる パーミッションのスーパーセットです。すなわち、 Django はいずれかのバックエ ンドのパーミッションを、どのユーザにも付与できます。

前述の単純なバックエンドで、万能の管理ユーザを作る方法は、以下のようにとても 簡単です:

class SettingsBackend(object):

    # ...

    def has_perm(self, user_obj, perm, obj=None):
        if user_obj.username == settings.ADMIN_LOGIN:
            return True
        else:
            return False

この書き方だと、上の例でアクセスを認可されたユーザにはあらゆるパーミッショ ンが許されます。バックエンドの認証関数はユーザオブジェクトを引数にとります。 また、ユーザオブジェクトの代わりに、 User のコンストラクタと同じ引数も指定 できます。

認可の API は、 django/contrib/auth/backends.py で実装されています。この バックエンドはデフォルトのバックエンドであり、ほとんどの場合 auth_permission にパーミッションを問い合わせます。

匿名ユーザへの権限

リリースノートを参照してください

匿名ユーザは認証されていません。すなわち、有効な認証の情報が提供されていませ ん。しかしながら、権限が与えられてないから何もしなくてよいという意味ではありま せん。最も基本的な部分で、ほとんどの Web サイトはサイトの大部分を匿名ユーザ に対して見せています。そして、許可された匿名ユーザはコメントなどを投稿する ことができます。

Django のパーミッションフレームワークは、匿名ユーザに対してのパーミッションを 保持する場所を設けてはいません。ですが、匿名ユーザに対しての権限を指定するため の認証バックエンドのカスタムは基礎部分で許可されています。これは特に、 再利用できるアプリの作者に取って役に立つものです。認証バックエンドに権限につい ての全ての問題を任せてしまうことが出来ます。セッティングを必要とするというより 、例が匿名ユーザのコントロールです。

アクティブでないユーザの権限

リリースノートを参照してください

アクティブでないユーザは、認証されていても is_activeFalse に セットされているユーザです。しかし、これは何も認証されていないという意味で はありません。例えば、そのようなユーザは自身のアカウントをアクティブにする ことができます。

パーミッションシステム内での匿名ユーザに対してのサポートは、アクティブでな いユーザがしない、「何かをする権限を得ること」を許可しています。

これをバックエンドで有効にするには、クラスの supports_inactive_user アトリビュートを True にしなければいけません。

supports_inactive_user 属性が存在しないことは、 PendingDeprecationWarning を送出します。もし、 Django 1.3 または、 1.4 ではこの警告は、 DeprecationWarning にアップデートされています。 これは大きくうるさげに表示されます。加えて、 supports_inactive_userFalse になっていると、 Django 1.5 ではアクティブでないユーザが 認証手続きでパスされることをサポートするでしょう。

オブジェクトへのパーミッションのハンドリング

Django のパーミッションフレームワークは、オブジェクトへのパーミッションを 基礎に持っています、でも、コアにその実装を持っていません。その意味は、 オブジェクトへのパーミッションは常に False が返るか、または空っぽの リスト(チェックがどう働いたかに依存します)が返ります。