手順 5: Django でユーザーを認証するStep 5: Authenticate users in Django

前の手順: 完全な Django Web プロジェクト テンプレートを使用するPrevious step: Use the full Django Web Project template

認証は Web アプリ共通のニーズであるため、"Django Web プロジェクト" テンプレートには基本認証フローが含まれています Because authentication is a common need for web apps, the "Django Web Project" template includes a basic authentication flow. (このチュートリアルの手順 6. で説明する "ポーリング Django Web プロジェクト" テンプレートにも、同じフローが含まれています)。いずれかの Django プロジェクト テンプレートを使用する場合、Visual Studio には Django プロジェクトの settings.py での認証に必要なすべてのモジュールが含まれています。(The "Polls Django Web Project" template discussed in step 6 of this tutorial also includes the same flow.) When using any of the Django project templates, Visual Studio includes all the necessary modules for authentication in the Django project's settings.py.

この手順では、次のことを学習します。In this step you learn:

  • Visual Studio テンプレートで提供される認証フローの使用方法 (手順 5-1)How to use the authentication flow provided in the Visual Studio templates (step 5-1)

手順 5-1: 認証フローを使用するStep 5-1: Use the authentication flow

次の手順では、認証フローを利用して、プロジェクトの関連する部分について説明します。The following steps exercise the authentication flow and describe the parts of the project that are involved:

  1. プロジェクトのルートにある readme.html ファイルの指示に従ってスーパー ユーザー (管理者) アカウントをまだ作成していない場合は、すぐに作成します。If you've not already followed the instructions in the readme.html file in the project root to create a super user (administrator) account, do so now.

  2. [デバッグ] > [デバッグの開始] (F5 キー) を使用して、Visual Studio からアプリを実行します。Run the app from Visual Studio using Debug > Start Debugging (F5). ブラウザーにアプリが表示されたら、ナビゲーション バーの右上に [ログイン] が表示されていることを確認します。When the app appears in the browser, observe that Log in appears on the upper right of the nav bar.

    Django Web プロジェクトのアプリ ページ上にある login コントロール

  3. templates/app/layout.html を開き、<div class="navbar ...> 要素にタグ {% include app/loginpartial.html %} が含まれていることを確認します。Open templates/app/layout.html and observe that the <div class="navbar ...> element contains the tag {% include app/loginpartial.html %}. {% include %} タグは、含まれているテンプレートにこの時点でインクルードされているファイルの内容を組み入れるように、Django のテンプレート システムに指示します。The {% include %} tag instructs Django's templating system to pull in the contents of the included file at this point in the containing template.

  4. templates/app/loginpartial.html を開き、{% else %} タグと共に条件タグ {% if user.is_authenticated %} を使用して、ユーザーが認証済みかどうかに応じて異なる UI 要素を表示する方法を確認します。Open templates/app/loginpartial.html and observe how it uses the conditional tag {% if user.is_authenticated %} along with an {% else %} tag to render different UI elements depending on whether the user has authenticated:

    {% if user.is_authenticated %}
    <form id="logoutForm" action="/logout" method="post" class="navbar-right">
        {% csrf_token %}
        <ul class="nav navbar-nav navbar-right">
            <li><span class="navbar-brand">Hello {{ user.username }}!</span></li>
            <li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li>
        </ul>
    </form>
    
    {% else %}
    
    <ul class="nav navbar-nav navbar-right">
        <li><a href="{% url 'login' %}">Log in</a></li>
    </ul>
    
    {% endif %}
    
  5. 最初にアプリを起動するときはどのユーザーも認証されていないので、このテンプレートのコードは、相対パス "login" への "ログイン" リンクのみを表示します。Because no user is authenticated when you first start the app, this template code renders only the "Log in" link to the relative path "login". (前のセクションで示したように) urls.py に指定されると、そのルートは django.contrib.auth.views.login ビューにマップされます。As specified in urls.py (as shown in the previous section), that route is mapped to the django.contrib.auth.views.login view. そのビューは、次のデータを受け取ります。That view receives the following data:

    {
        'template_name': 'app/login.html',
        'authentication_form': app.forms.BootstrapAuthenticationForm,
        'extra_context':
        {
            'title': 'Log in',
            'year': datetime.now().year,
        }
    }
    

    ここで、template_name は、ログイン ページ用のテンプレート (この場合は templates/app/login.html) を特定します。Here, template_name identifies the template for the login page, in this case templates/app/login.html. extra_context プロパティは、テンプレートに指定された既定のコンテキスト データに追加されます。The extra_context property is added to the default context data given to the template. 最後に、authentication_form は、テンプレートに form オブジェクトとして示される、ログインに使用するフォーム クラスを定義します。Finally, authentication_form specifies a form class to use with the login; in the template it appears as the form object. 既定値は AuthenticationForm (django.contrib.auth.views より) です。Visual Studio プロジェクト テンプレートでは代わりに、アプリの forms.py ファイルに定義された次のフォームを使用します。The default value is AuthenticationForm (from django.contrib.auth.views); the Visual Studio project template instead uses the form defined in the app's forms.py file:

    from django import forms
    from django.contrib.auth.forms import AuthenticationForm
    from django.utils.translation import ugettext_lazy as _
    
    class BootstrapAuthenticationForm(AuthenticationForm):
        """Authentication form which uses boostrap CSS."""
        username = forms.CharField(max_length=254,
                                   widget=forms.TextInput({
                                       'class': 'form-control',
                                       'placeholder': 'User name'}))
        password = forms.CharField(label=_("Password"),
                                   widget=forms.PasswordInput({
                                       'class': 'form-control',
                                       'placeholder':'Password'}))
    

    見てわかるように、このフォーム クラスは AuthenticationForm から派生し、明示的にユーザー名とパスワードのフィールドをオーバーライドして、プレースホルダ― テキストを追加します。As you can see, this form class derives from AuthenticationForm and specifically overrides the username and password fields to add placeholder text. Visual Studio テンプレートには、パスワード強度の検証を追加するなど、必要に応じてフォームをカスタマイズすることを予想して、この明示的なコードが含まれています。The Visual Studio template includes this explicit code on the assumption that you likely want to customize the form, such as adding password strength validation.

  6. ログイン ページに移動すると、アプリは login.html テンプレートを表示します。When you navigate to the login page, then, the app renders the login.html template. 変数 {{ form.username }} および {{ form.password }} は、BootstrapAuthenticationForm から CharField フォームを表示します。The variables {{ form.username }} and {{ form.password }} render the CharField forms from BootstrapAuthenticationForm. また、検証エラーを表示するための組み込みのセクションと、ソーシャル ログイン用にあらかじめ用意されている要素もあり、必要に応じてこれらのサービスを追加できます。There's also a built-in section to show validation errors, and a ready-made element for social logins if you choose to add those services.

    {% extends "app/layout.html" %}
    
    {% block content %}
    
    <h2>{{ title }}</h2>
    <div class="row">
        <div class="col-md-8">
            <section id="loginForm">
                <form action="." method="post" class="form-horizontal">
                    {% csrf_token %}
                    <h4>Use a local account to log in.</h4>
                    <hr />
                    <div class="form-group">
                        <label for="id_username" class="col-md-2 control-label">User name</label>
                        <div class="col-md-10">
                            {{ form.username }}
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="id_password" class="col-md-2 control-label">Password</label>
                        <div class="col-md-10">
                            {{ form.password }}
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="col-md-offset-2 col-md-10">
                            <input type="hidden" name="next" value="/" />
                            <input type="submit" value="Log in" class="btn btn-default" />
                        </div>
                    </div>
                    {% if form.errors %}
                    <p class="validation-summary-errors">Please enter a correct user name and password.</p>
                    {% endif %}
                </form>
            </section>
        </div>
        <div class="col-md-4">
            <section id="socialLoginForm"></section>
        </div>
    </div>
    
    {% endblock %}
    
  7. フォームを送信すると、Django は資格情報 (スーパー ユーザーの資格情報など) の認証を試みます。When you submit the form, Django attempts to authenticate your credentials (such as the super user's credentials). 認証に失敗した場合、現在のページに留まりますが、form.errors は true に設定されます。If authentication fails, you remain on the current page but form.errors set to true. 認証に成功した場合、Django は "next" フィールド <input type="hidden" name="next" value="/" /> にある相対 URL に移動します。この例では、ホーム ページ (/) になっています。If authentication is successful, Django navigates to the relative URL in the "next" field, <input type="hidden" name="next" value="/" />, which in this case is the home page (/).

  8. ここで、ホーム ページが再表示されると、loginpartial.html テンプレートが表示されるときに、user.is_authenticated プロパティが true になります。Now, when the home page is rendered again, the user.is_authenticated property is true when the loginpartial.html template is rendered. その結果、Hello (<ユーザー名>) メッセージと [Log off] が表示されます。As a result, you see a Hello (username) message and Log off. アプリの他の部分で user.is_authenticated を使用して、認証を確認できます。You can use user.is_authenticated in other parts of the app to check authentication.

    [Django Web プロジェクト] アプリ ページ上の Hello メッセージとログオフ コントロール

  9. 認証済みユーザーに特定のリソースに対するアクセス権が付与されたかどうかを確認するには、ユーザー固有のアクセス許可をデータベースから取得する必要があります。To check whether the authenticated user is authorized to access specific resources, you need to retrieve user-specific permissions from your database. 詳細については、Django 認証システムの使用に関するページ (Django docs) を参照してください。For more information, see Using the Django authentication system (Django docs).

  10. 特に、ス―パー ユーザーまたは管理者は、相対 URL "/admin/" および "/admin/doc/" を使用して、組み込みの Django 管理者インターフェイスにアクセスします。The super user or administrator, in particular, is authorized to access the built-in Django administrator interfaces using the relative URLs "/admin/" and "/admin/doc/". これらのインターフェイスを有効にするには、次の手順を実行します。To enable these interfaces, do the following:

    1. 環境に docutils Python パッケージをインストールします。Install the docutils Python package into your environment. そのためには、requirements.txt ファイルに "docutils" を追加し、ソリューション エクスプローラーでプロジェクトを展開し、[Python 環境] ノードを選択してから、使用している環境を右クリックして [requirements.txt からインストール] を選択することをお勧めします。A great way to do this is to add "docutils" to your requirements.txt file, then in Solution Explorer, expand the project, expand the Python Environments node, then right-click the environment you're using an select Install from requirements.txt.

    2. Django プロジェクトの urls.py を開き、次のエントリから既定のコメントを削除します。Open the Django project's urls.py and remove the default comments from the following entries:

      from django.conf.urls import include
      from django.contrib import admin
      admin.autodiscover()
      
      # ...
      urlpatterns = [
          # ...
          url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
          url(r'^admin/', include(admin.site.urls)),
      ]
      
    3. Django プロジェクトの settings.py ファイルで、INSTALLED_APPS コレクションに移動して 'django.contrib.admindocs' を追加します。In the Django project's settings.py file, navigate to the INSTALLED_APPS collection and add 'django.contrib.admindocs'.

    4. アプリを再起動したときに、"/admin/" および "/admin/doc/" に移動して、追加のユーザー アカウント作成などのタスクを実行できます。When you restart the app, you can navigate to "/admin/" and "/admin/doc/" and perform tasks like creating additional user accounts.

      Django 管理者インターフェイス

  11. 認証フローの最後の部分は、ログオフです。The final part to the authentication flow is logging off. loginpartial.html でわかるように、[Log off] リンクは単純に相対 URL "/login" に対する POST を実行します。これは、組み込みのビュー django.contrib.auth.views.logout によって処理されます。As you can see in loginpartial.html, the Log off link simply does a POST to the relative URL "/login", which is handled by the built-in view django.contrib.auth.views.logout. このビューには UI が表示されず、ホーム ページへの移動のみを行います (urls.py の "^logout$" パターンで確認できます)。This view doesn't display any UI and just navigates to the home page (as shown in urls.py for the "^logout$" pattern). ログオフ ページを表示する場合は、最初に、次のように URL パターンを変更して、"template_name" プロパティを追加し "next_page" プロパティを削除します。If you want to display a logoff page, first change the URL pattern as follows to add a "template_name" property and remove the "next_page" property:

    url(r'^logout$',
        django.contrib.auth.views.logout,
        {
            'template_name': 'app/loggedoff.html',
            # 'next_page': '/',
        },
        name='logout')
    

    次に、以下の (最小限の) 内容で templates/app/loggedoff.html を作成します。Then create templates/app/loggedoff.html with the following (minimal) contents:

    {% extends "app/layout.html" %}
    {% block content %}
    <h3>You have been logged off</h3>
    {% endblock %}
    

    結果として、次のように表示されます。The result appears as follows:

    追加されたログオフ ページ

  12. すべて完了したら、サーバーを停止し、もう一度ソース管理に変更をコミットします。When you're all done, stop the server and once again commit your changes to source control.

質問: <form> 要素に表示される {% csrf_token %} タグの目的は何ですか。Question: What is the purpose of the {% csrf_token %} tag that appears in the <form> elements?

回答: {% csrf_token %} タグには Django の組み込みのクロスサイト リクエスト フォージェリ (csrf) 保護 (Django docs) が含まれています。Answer: The {% csrf_token %} tag includes Django's built-in cross-site request forgery (csrf) protection (Django docs). このタグは通常、フォームなどの POST、PUT、または DELETE 要求のメソッドに関連する任意の要素に追加します。You typically add this tag to any element that involves POST, PUT, or DELETE request methods, such as a form. その後、テンプレートのレンダリング関数 (render) により、必要な保護が挿入されます。The template rendering function (render) then inserts the necessary protection.

次の手順Next steps

詳しい説明Go deeper