教程:在 Visual Studio 中使用 Django 对用户进行身份验证

本文介绍教程系列中的步骤 5 在 Visual Studio中使用 Django Web 框架。

身份验证是 Web 应用的常见要求。 Visual Studio 中的 Django Web 项目 模板提供了在 Django 项目的 settings.py 文件中进行身份验证所需的所有模块。 本教程系列中的步骤 4 使用此模板创建 Django Web 应用。 在步骤 5 中,你将探索模板的身份验证功能,并处理正在运行的应用中的功能。

在本教程的步骤 5 中,你将了解如何:

  • 在 Visual Studio 的 Django Web 项目模板中浏览身份验证流
  • 检查支持身份验证过程的代码
  • 修改代码以启用对 Django 管理员接口的访问
  • 运行 Django Web 应用并使用身份验证功能

先决条件

探索身份验证流程

本部分介绍 Django Web 应用的 Django Web 项目 模板提供的默认身份验证流。

  1. 在 Visual Studio 中,选择 调试>启动调试F5)以启动 Django Web 应用(DjangoWeb)。

  2. 当应用在浏览器中打开时,请注意导航栏右侧 登录 选项:

    显示正在运行的 Django Web 应用中导航栏上的“登录”选项的屏幕截图。

    正在运行的 Django 应用具有三个页面选项的导航栏,主页关于联系人,以及 登录 选项。 身份验证配置允许任何用户查看“主页”、“关于”和“联系人”页面上的内容。

  3. 对于对 Django Web 应用的身份验证访问,指定的超级用户可以使用 登录 选项,这将打开“登录”页面:

    显示正在运行的 Django Web 应用中超级用户的登录身份验证页的屏幕截图。

  4. 超级用户登录后,他们可以访问网站的受限页面视图并完成管理任务:

    屏幕截图,其中显示了 Django 超级用户可用的页面视图之一,以及带有注销选项的更新导航栏。

  5. 超级用户可以使用 注销 选项注销 Django Web 应用,并作为未经身份验证的用户返回到 Django Web 应用的“主页”。

在以下部分中,将修改身份验证配置以支持超级用户的 Django 管理站点访问。

检查身份验证代码

了解 Django Web 应用的常规身份验证功能后,即可检查由 Django Web 项目 模板提供的基础代码:

  1. 解决方案资源管理器中,展开项目的 app/templates/app 文件夹。 以下步骤查看此文件夹中的多个文件。

  2. 打开基本模板文件,layout.html。 滚动到 <div class="navbar ...> 元素并找到 {% include app/loginpartial.html %} 标记。

    {% include %} 标记指示 Django 的模板化系统在包含模板中此时所含的文件内容中进行拉取。

  3. 打开 loginpartial.html 文件。 观察此模板如何使用条件标记 {% if user.is_authenticated %} 以及 {% else %} 标记来呈现不同的 UI 元素,具体取决于用户是否已进行身份验证:

    {% 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 %}
    
  4. 启动应用时,不会对超级用户进行身份验证,模板代码仅呈现 登录 链接。 链接以 Django 项目的 URL 文件(DjangoWeb/DjangoWeb/urls.py)中指定的网站相对“登录”路径为目标,如 步骤 4(检查 URL 路由模式)中所述。 “login”路由被映射到标记为 django.contrib.auth.views.login 的视图,视图接收以下数据:

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

    此代码定义三个属性:

    • template_name 标识 应用/login.html 文件中定义的“登录”页面的模板。 请记住,此链接是站点相对链接。 完整文件夹路径 app/templates/app/login.html

    • extra_context 向模板提供的默认上下文数据添加信息。 在这种情况下,信息包括“登录”标题以及日期、时间和年份。

    • authentication_form 指定一个窗体类用于登录过程。 在模板中,此属性值显示为 form 对象。 默认值为 AuthenticationForm(从 django.contrib.auth.views),但 Visual Studio 项目模板改用项目 应用/forms.py文件中定义的表单:

      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 bootstrap 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,并专门替代用户名和密码字段以添加占位符文本。 Visual Studio 模板包含此显式代码,假设你可能想要自定义表单,例如添加密码强度验证。

  5. 当用户与应用进行交互并打开“登录”页面时,应用将呈现 login.html 模板。 变量 {{ form.username }}{{ form.password }} 呈现来自 BootstrapAuthenticationForm 类的 CharField 窗体。 还有一个内置部分,用于显示验证错误,如果你选择添加这些服务,则为社交登录提供现成的元素:

    {% 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 %}
    
  6. 当用户在页面窗体中选择 登录 时,Django 会尝试对凭据进行身份验证,例如超级用户的凭据:

    • 如果身份验证失败,用户将保留在“登录”页上,form.errors 标记设置为 true:

      显示当用户在 Django 登录过程中输入不正确凭据时显示消息的屏幕截图。

    • 如果身份验证成功,Django 将在 next 字段中打开相对 URL,<input type="hidden" name="next" value="/" />,在本例中为“主页”(/)。

  7. 当应用在用户进行身份验证后呈现“主页”页面时,呈现 loginpartial.html 模板时,user.is_authenticated 属性为 true。 在这种情况下,导航栏显示 Hello(用户名) 消息,注销 选项将替换 登录 选项:

    屏幕截图,显示经过身份验证的用户的更新导航栏,其中包含 Hello 消息和注销选项。

    可以使用应用代码的其他部分中的 user.is_authenticated 属性来检查身份验证。

访问 Django 管理员接口

若要检查经过身份验证的用户是否有权访问特定资源,需要从数据库中检索特定于用户的权限。

特别是超级用户或管理员,有权使用网站相对 URL /admin//admin/doc/访问内置的 Django 管理员接口。 有关详细信息,请参阅 使用 Django 身份验证系统(Django docs)。

若要启用对 Django 管理员接口的访问权限,请执行以下步骤:

  1. docutils Python 包安装到环境中。 请参阅 Python 环境包的安装说明

  2. 解决方案资源管理器中,展开 Django 项目文件夹,DjangoWeb/DjangoWeb/。 以下步骤更新此文件夹中的多个文件。

  3. 打开 Django 项目的 urls.py 文件并修改内容,如下所示:

    1. 在文件的顶部,将 URL 的以下包导入添加到当前列表的末尾:

      from django.conf.urls import include
      
    2. 导入列表后,添加以下语句:

      admin.autodiscover()
      
    3. 找到 urlpatterns 定义,并在 'admin/' 项之前添加以下路径条目

      path('admin/doc/', include('django.contrib.admindocs.urls')),
      
  4. 打开 Django 项目的 settings.py 文件,找到 INSTALLED_APPS 集合。 紧跟 app 条目后添加以下条目

    'django.contrib.admindocs',
    
  5. 停止并重启 Django Web 应用。

  6. 在浏览器的 URL 地址字段中,将应用的页面视图更改为 /admin//admin/doc/ 路由。 这些页面为超级用户提供对 Django 管理任务的访问权限,例如创建用户或组帐户、更改密码以及查看 Django 文档:

    屏幕截图,显示 Django Web 应用中经过身份验证的超级用户 Django 文档的示例页面视图。

研究退出登录行为

超级用户可以通过两种方式注销和结束经过身份验证的会话。 Django Web 应用包括导航栏上的 注销 选项,Django 管理站点提供 注销 选项。

从 Django 管理站点退出登录

如果超级用户正在查看 Django 管理网站上的页面,则可以在网站导航栏上选择“注销”。 浏览器将刷新以显示网站的“退出登录”页面:

显示超级用户从 Django 管理站点退出登录后的“已退出登录”页面。

在此页上,用户有两个选项,主页再次登录。 这两个选项均将用户返回到 Django 管理网站(/admin)的“主页”页面,提示用户重新输入其凭据。

显示 Django 管理站点的“登录”对话框的屏幕截图。

从 Django Web 应用退出登录

如果超级用户正在 Django Web 应用中查看“关于”或“联系信息”等页面,则他们可以在 Django Web 应用导航栏中选择“退出登录”。 退出登录行为是最小的行为。 它只是结束经过身份验证的会话,并将用户浏览回应用“主页”。

可以重新设计注销行为,使其对用户更有信息价值。

  1. 在解决方案资源管理器 中,展开项目的 应用/模板/应用 文件夹,然后打开 loginpartial.html 文件。

  2. 在模板文件中,请注意,“注销”链接只是对站点相对 URL 路径“/login”(href="{% url 'login' %}") 执行 HTTP POST (action="/logout" method="post") 操作

    {% 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 %}
    

    内置视图 django.contrib.auth.views.logout 函数处理此注销过程。

    当前行为并未显示任何 UI 来通知用户其已退出登录。 此过程只是根据 Django 项目的 URL 文件 (DjangoWeb/DjangoWeb/urls.py) 中定义的 'logout/' 路径模式将用户带回 Django Web 应用的“主页”页面

     path('logout/', LogoutView.as_view(next_page='/'), name='logout'),
    

    若要显示更丰富的注销确认信息,可以为应用创建“注销”页。

  3. 应用/模板/应用 文件夹中,创建名为 loggedoff.html的新 HTML 模板文件。

  4. 将以下内容添加到新模板文件:

    {% extends "app/layout.html" %}
    {% block content %}
    <h3>You have been logged off</h3>
    {% endblock %}
    
  5. 在 Django 项目的 URL 文件中,DjangoWeb/DjangoWeb/urls.py更改 'logout/' 路径的 URL 模式,如下所示:

    path('logout/', LogoutView.as_view(template_name='app/loggedoff.html'), name='logout'),
    

    更新的代码将添加一个 template_name 属性,以便与“已注销”页的新 HTML 模板配合使用。

  6. 停止并重启 Django Web 应用。 再次登录,然后选择“退出登录”。 这一次,应用向用户显示一条信息性更丰富的消息,以确认他们已注销:

    屏幕截图,显示 Django Web 应用的更新后的注销行为和“注销”页上的消息。

  7. 停止服务器并关闭应用程序浏览器窗口。

将项目保存到版本控制系统

如果你在本教程系列的整个过程中将 Visual Studio 解决方案提交到源代码控制,现在是进行一次新的提交的好时机。 按照本教程系列中的步骤 2(提交对源代码管理所做的更改)中的说明操作。

解决方案应与 GitHub 上的教程源代码匹配:Microsoft/python-sample-vs-learning-django

在窗体元素中使用 {% csrf_token %} 标记

{% csrf_token %} 标记包含 Django 的内置跨网站请求伪造 (csrf) 保护(Django 文档)。 通常将此标记添加到涉及 POST、PUT 或 DELETE 请求方法(如窗体)的任何元素。 然后,模板呈现函数(render)插入必要的保护。

教程评审

祝贺你完成 Visual Studio 中 Django 的本教程。

在本教程中,你将了解:

  • 在 Visual Studio 中使用各种模板生成不同类型的 Django 项目
  • 创建包含多个页面的 Django Web 应用
  • 使用模板创建不同的路由和页面视图
  • 提供静态文件、添加页面和使用模板继承
  • 提供对受限应用页面和功能以及 Django 管理界面的经过身份验证的访问权限