django认证系统 Authentication使用详解

前言

Django自带一个用户认证系统,用于处理用户账户、群组、许可和基于cookie的用户会话。

Django的认证系统包含了身份验证和权限管理两部分。简单地说,身份验证用于核实某个用户是否合法,权限管理则是决定一个合法用户具有哪些权限。往后,‘认证'这个词同时代指上面两部分的含义。

Django的认证系统主要包括下面几个部分:

  • 用户
  • 许可
  • 可配置的密码哈希系统
  • 用于用户登录或者限制访问的表单和视图工具
  • 可插拔的后台系统

类似下面的问题,不是Django认证系统的业务范围,请使用第三方工具:

  • 密码强度检查
  • 登录请求限制
  • 第三方认证

默认情况下,使用django-admin startproject命令后,认证相关的模块已经自动添加到settings文件内了,如果没有的话,请手动添加。

在INSTALLED_APPS配置项中添加:

  • 'django.contrib.auth': 包含认证框架的核心以及默认模型
  • 'django.contrib.contenttypes':内容类型系统,用于给模型关联许可

在MIDDLEWARE配置项中添加:

  • SessionMiddleware:通过请求管理会话
  • AuthenticationMiddleware:将会话和用户关联

当配置正确后,运行manage.py migrate命令,创建用户认证系统相关的数据库表以及分配预定义的权限。

一、用户对象

用户对象是Django认证系统的核心!在Django的认证框架中只有一个用户模型也就是User模型,它位于django.contrib.auth.models。

本节内容叙述的所有功能,都是基于这个User模型的,和这个User模型没有任何关系的自定义用户模型是无法使用Django认证系统的功能的!

用户模型主要有下面几个字段:

  • username
  • password
  • email
  • first_name
  • last_name

1. 创建用户

要创建一个新用户,最直接的办法是使用create_user()方法:

>>> from django.contrib.auth.models import User
>>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')
# 这时,user是一个User类的实例,已经保存在了数据库内,你可以随时修改它的属性,例如:
>>> user.last_name = 'Lennon'
>>> user.save()

如果你已经启用了Django的admin站点,你也可以在后台创建用户。

2. 创建超级用户

使用createsuperuser命令,创建超级用户:

$ python manage.py createsuperuser

或者

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

根据提示输入名字、密码和邮箱地址。密码要有一定强度

3. 修改密码

Django默认会对密码进行加密,因此,不要企图对密码进行直接操作。

要修改密码,有两个办法:

  • 使用命令行: python manage.py changepassword username。如果不提供用户名,则会尝试修改当前系统用户的密码。
  • 使用set_password()方法:
from django.contrib.auth.models import User
u = User.objects.get(username='john')
u.set_password('new password')
u.save()

同样可以在admin中修改密码。Django提供了views和forms,方便用户自己修改密码。 修改密码后,用户的所有当前会话将被注销。

4. 用户验证

利用authenticate()方法,对用户进行验证。该方法通常接收username与password作为参数。要注意的是,认证的后端可能有好几个,有一项认证通过则返回一个User类对象,一项都没通过或者抛出了PermissionDenied异常,则返回一个None。例如:

from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:
  # A backend authenticated the credentials
else:
  # No backend authenticated the credentials

二、 权限与授权

Django提供了一个简单的权限系统,并且已经用于它的admin站点,当然你也可以在你的代码中使用。

User模型的对象有两个多对多的字段:groups和user_permissions,可以像下面这样访问他们:

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

1. 默认权限

默认情况下,使用manage.py migrate命令时,Django会给每个已经存在的model添加默认的权限。 假设你现在有个app叫做foo,有个model叫做bar,使用下面的方式可以测试默认权限:

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

2. 用户组

Django提供了一个django.contrib.auth.models.Group模型,该model可用于给用户分组,实现批量管理。用户和组属于多对多的关系。用户自动具有所属组的所有权限。

3. 在代码中创建权限

例如,为myapp中的BlogPost模型添加一个can_publish权限。

from myapp.models import BlogPost
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType

content_type = ContentType.objects.get_for_model(BlogPost)
permission = Permission.objects.create(
  codename='can_publish',
  name='Can Publish Posts',
  content_type=content_type,
)

然后,你可以通过User模型的user_permissions属性或者Group模型的permissions属性为用户添加该权限。

4. 权限缓存

权限检查后,会被缓存在用户对象中。参考下面的例子:

from django.contrib.auth.models import Permission, User
from django.shortcuts import get_object_or_404

def user_gains_perms(request, user_id):
  user = get_object_or_404(User, pk=user_id)
  # any permission check will cache the current set of permissions
  user.has_perm('myapp.change_bar')

  permission = Permission.objects.get(codename='change_bar')
  user.user_permissions.add(permission)

  # Checking the cached permission set
  user.has_perm('myapp.change_bar') # False

  # Request new instance of User
  # Be aware that user.refresh_from_db() won't clear the cache.
  user = get_object_or_404(User, pk=user_id)

  # Permission cache is repopulated from the database
  user.has_perm('myapp.change_bar') # True

  ...

三、 在视图中认证用户

Django使用session和中间件关联请求对象中和认证系统。

每一次请求中都包含一个request.user属性,表示当前用户。如果该用户未登陆,该属性的值是一个AnonymousUser实例(匿名用户),如果已经登录,该属性就是一个User模型的实例。

可以使用is_authenticated方法进行判断,如下:

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

1. 如何登录用户

在视图中,使用认证系统的login()方法登录用户。它接收一个HttpRequest参数和一个User对象参数。该方法会把用户的ID保存在Django的session中。下面是一个认证和登陆的例子:

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:
    login(request, user)
    # 跳转到成功页面
    ...
  else:
    # 返回一个非法登录的错误页面
    ...

2. 如何注销用户

logout(request)[source]:

from django.contrib.auth import logout

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

注意,被logout的用户如何没登录,不会抛出错误。 一旦logout,当前请求中的session数据都会被清空。

3. 限制用户的访问权限

很多时候,我们要区分已登录用户和未登录用户,只对登录的用户开放一些页面或功能,限制未登录用户的行为。办法有很多,下面是主要几种:

1.原始的办法:

如果用户未登录,重定向到登录页面,如下所示:

from django.conf import settings
from django.shortcuts import redirect

def my_view(request):
  if not request.user.is_authenticated:
    return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
  # ...

或者显示一个错误信息:

from django.shortcuts import render

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

2. 使用装饰器

原型:login_required(redirect_field_name='next', login_url=None)[source]

被该装饰器装饰的视图,强制要求用户必须登录后才可以访问。

from django.contrib.auth.decorators import login_required

@login_required
def my_view(request):
  ...

该装饰器工作机制:

  • 如果用户未登陆,重定向到settings.LOGIN_URL,传递当前绝对路径作为url字符串的参数,例如:/accounts/login/?next=/polls/3/
  • 如果用户已经登录,执行正常的视图

此时,默认的url中使用的参数是“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变量。

login_required()装饰器还有一个可选的longin_url参数。例如:

from django.contrib.auth.decorators import login_required

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

注意:如果不指定login_url参数,请确保你的settings.LOGIN_URL和登陆视图保持正确的关联。例如:

from django.contrib.auth import views as auth_views
url(r'^accounts/login/$', auth_views.login),

3. 使用LoginRequired mixin

通过继承LoginRequiredMixin类的方式限制用户。在多继承时,该类必须是最左边的父类。

from django.contrib.auth.mixins import LoginRequiredMixin

class MyView(LoginRequiredMixin, View):
  login_url = '/login/'
  redirect_field_name = 'redirect_to'

4. 进行测试,根据结果决定动作

也可以直接在视图中进行过滤:

from django.shortcuts import redirect

def my_view(request):
  if not request.user.email.endswith('@example.com'):
    return redirect('/login/?next=%s' % request.path)
  # ...

上面根据用户的邮箱地址,判断用户的权限。

5. 使用权限需求装饰器

Django内置了一个permission_required()装饰器,用户根据用户权限,决定视图的访问权限,如下所示:

from django.contrib.auth.decorators import permission_required

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

权限的格式是<app label>.<permission codename>。

该装饰器还有一个可选的longin_url参数:

from django.contrib.auth.decorators import permission_required

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

4. 认证视图

Django为我们提供了一系列认证相关的视图,可以直接拿来用,这样你就不需要自己写登录、注销、注册等视图。但是,但是,Django没有为认证视图提供默认的模板,你需要自己写......。

所以,除非懒癌发作,还是老老实实自己写认证相关的视图、路由和模板吧。个人认为类似跟实际生产环境结合非常紧密的视图,根本不需要这种鸡肋的内置视图,到最后,你发现还是要自己写才能满足需求。

所以,后面的部分就不赘述了!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 利用Django内置的认证视图实现用户密码重置功能详解

    前言 密码重置功能相信对大家来说都不陌生,本文主要给大家介绍了关于使用Django内置的认证视图实现简单的通过邮箱重置密码的功能,分享出来供大家参考学习,下面话不多说了,来一起来看看详细的介绍吧. 版本: django 1.11 实现方法 在django.contrib.auth.views中提供了四个类视图用于密码重置 class PasswordResetView URL name: password_reset  #要保持相同 通过给邮箱发送重置密码的链接进行密码重置.注意如果邮箱不存在,

  • 详解Django之auth模块(用户认证)

    auth模块简介 auth模块是对登录认证方法的一种封装,之前我们获取用户输入的用户名及密码后需要自己从user表里查询有没有用户名和密码符合的对象, 而有了auth模块之后就可以很轻松的去验证用户的登录信息是否存在于数据库中. 除此之外,auth还对session做了一些封装,方便我们校验用户是否已登录 auth里的方法 如果想使用auth模块的方法,必须要先导入auth模块 from django.contrib import auth django.contrib.auth中提供了许多方法

  • 浅谈django中的认证与登录

    认证登录 django.contrib.auth中提供了许多方法,这里主要介绍其中的三个: 1  authenticate(**credentials)    提供了用户认证,即验证用户名以及密码是否正确 一般需要username  password两个关键字参数 如果认证信息有效,会返回一个  User  对象.authenticate()会在User 对象上设置一个属性标识那种认证后端认证了该用户,且该信息在后面的登录过程中是需要的.当我们试图登陆一个从数据库中直接取出来不经过authent

  • 深入理解Django中内置的用户认证

    前言 本文主要给大家介绍了关于Django中内置用户认证的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 认证登陆 在进行用户登陆验证的时候,如果是自己写代码,就必须要先查询数据库,看用户输入的用户名是否存在于数据库中: 如果用户存在于数据库中,然后再验证用户输入的密码,这样一来就要自己编写大量的代码. 事实上,Django已经提供了内置的用户认证功能. 在使用"python manage.py makemigrationss"和"python m

  • django认证系统 Authentication使用详解

    前言 Django自带一个用户认证系统,用于处理用户账户.群组.许可和基于cookie的用户会话. Django的认证系统包含了身份验证和权限管理两部分.简单地说,身份验证用于核实某个用户是否合法,权限管理则是决定一个合法用户具有哪些权限.往后,'认证'这个词同时代指上面两部分的含义. Django的认证系统主要包括下面几个部分: 用户 许可 组 可配置的密码哈希系统 用于用户登录或者限制访问的表单和视图工具 可插拔的后台系统 类似下面的问题,不是Django认证系统的业务范围,请使用第三方工具

  • Ubuntu系统搭建django+nginx+uwsgi的教程详解

    1. 在开发机上的准备工作 1.确认项目没有bug. 2.用pip freeze > requirements.txt将当前环境的包导出到requirements.txt文件中,方便在部署的时候安装. 3.将项目上传到服务器上的/srv目录下.这里以git的形式为例,打开终端,依次输入如下命令 •git init •git remote add origin xxx.git •git add . •git commit -m 'first commit' •git pull origin mas

  • django 微信网页授权认证api的步骤详解

    微信网页授权认证 根据微信官方文档,网页授权需要四个步骤, - 用户同意授权-获取code - 通过code 获取网页授权access_token - 通过code 获取网页授权access_token - 刷新token - 拉去用户信息scope为snsapi_userinfo -检验授权凭证 access_token是否有效 1 授权 url="https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirec

  • 基于Django contrib Comments 评论模块(详解)

    老版本的Django中自带一个评论框架.但是从1.6版本后,该框架独立出去了,也就是本文的评论插件. 这个插件可给models附加评论,因此常被用于为博客文章.图片.书籍章节或其它任何东西添加评论. 一.快速入门 快速使用步骤: 安装包:pip install django-contrib-comments 在django的settings中的INSTALLED_APPS处添加'django.contrib.sites'进行app注册,并设置SITE_ID值. 在django的settings中

  • Django REST Framework 分页(Pagination)详解

    在前面的DRF系列教程中,我们以博客为例介绍了序列化器, 使用基于类的视图APIView和ModelViewSet开发了针对文章资源进行增删查改的完整API端点,并详细对权限和认证(含jwt认证)进行了总结与演示.在本篇文章中我们将向你演示如何在Django REST Framework中使用分页. 分页 为什么要分页? 当你的数据库数据量非常大时,如果一次将这些数据查询出来, 必然加大了服务器内存的负载,降低了系统的运行速度.一种更好的方式是将数据分段展示给用户.如果用户在展示的分段数据中没有

  • Django权限机制实现代码详解

    本文研究的主要是Django权限机制的相关内容,具体如下. 1. Django权限机制概述 权限机制能够约束用户行为,控制页面的显示内容,也能使API更加安全和灵活:用好权限机制,能让系统更加强大和健壮.因此,基于Django的开发,理清Django权限机制是非常必要的. 1.1 Django的权限控制 Django用user, group和permission完成了权限机制,这个权限机制是将属于model的某个permission赋予user或group,可以理解为全局的权限,即如果用户A对数

  • MongoDB开启权限认证的方法步骤详解

    前言 最近在生产环境中MongoDB已经使用有一段时间了,但对于MongoDB的数据存储一直没有使用到权限访问(MongoDB默认设置为无权限访问限制),最近在酷壳网看了一篇技术文章(https://coolshell.cn/?s=从+MONGODB+"赎金事件"+看安全问题&from=timeline&isappinstalled=0)介绍的mongodb未开启权限认证导致数据被黑客窃取,要比特币赎回的事件,考虑到数据安全的原因特地花了一点时间研究了一下,我现在用的版

  • Django中的Signal代码详解

    本文研究的主要是Django开发中的signal 的相关内容,具体如下. 前言 在web开发中, 你可能会遇到下面这种场景: 在用户完成某个操作后, 自动去执行一些后续的操作. 譬如用户完成修改密码后, 你要发送一份确认邮件. 当然可以把逻辑写在一起,但是有个问题是,触发操作一般不止一种(如用户更改了其它信息的确认邮件),这时候这个逻辑会需要写多次,所以你可能会想着DRY(Don't repeat yourself),于是你把它写到了一个函数中,每次调用.当然这是没问题的. 但是, 如果你换个思

  • Django mysqlclient安装和使用详解

    一.安装mysqlclient 网上看到很过通过命令:pip install mysqlclient 进行安装的教程,但是我却始终安装失败,遇到的错误千奇百怪,后来通过自己下载mysqlclient客户端终于安装成功: 首先打开网址:https://www.lfd.uci.edu/~gohlke/pythonlibs/并找到下面图中的内容部分: 根据自己的需要,我选择的是最下边的cp38(目测cp38应该是C++版本,下载下来的文件通过pip install 进行安装的时候会进行c++编译,如果

  • Django url 路由匹配过程详解

    1 Django 如何处理一个请求 当一个用户请求Django 站点的一个页面,下面是Django 系统决定执行哪个Python 代码使用的算法: Django 确定使用根 URLconf 模块.通常,这是 ROOT_URLCONF 设置的值(即 settings 中的 ROOT_URLCONF),但如果传入 HttpRequest 对象拥有 urlconf 属性(通过中间件设置),它的值将被用来代替 ROOT_URLCONF 设置.可以在 django/core/handlers/base.p

随机推荐