侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

django认证系统 Authentication使用详解

框架(架构)  /  管理员 发布于 7年前   294

前言

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', '[email protected]', 'johnpassword')# 这时,user是一个User类的实例,已经保存在了数据库内,你可以随时修改它的属性,例如:>>> user.last_name = 'Lennon'>>> user.save()

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

2. 创建超级用户

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

$ python manage.py createsuperuser

或者

$ python manage.py createsuperuser --username=joe [email protected]

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

3. 修改密码

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

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

  • 使用命令行: python manage.py changepassword username。如果不提供用户名,则会尝试修改当前系统用户的密码。
  • 使用set_password()方法:
from django.contrib.auth.models import Useru = 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 authenticateuser = authenticate(username='john', password='secret')if user is not None:  # A backend authenticated the credentialselse:  # 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 BlogPostfrom django.contrib.auth.models import Permissionfrom django.contrib.contenttypes.models import ContentTypecontent_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, Userfrom django.shortcuts import get_object_or_404def 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, logindef 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 logoutdef logout_view(request):  logout(request)  # Redirect to a success page.

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

3. 限制用户的访问权限

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

1.原始的办法:

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

from django.conf import settingsfrom django.shortcuts import redirectdef my_view(request):  if not request.user.is_authenticated:    return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))  # ...

或者显示一个错误信息:

from django.shortcuts import renderdef 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_requireddef 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_viewsurl(r'^accounts/login/$', auth_views.login),

3. 使用LoginRequired mixin

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

from django.contrib.auth.mixins import LoginRequiredMixinclass MyView(LoginRequiredMixin, View):  login_url = '/login/'  redirect_field_name = 'redirect_to'

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

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

from django.shortcuts import redirectdef 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没有为认证视图提供默认的模板,你需要自己写......。

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

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

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


  • 上一条:
    django 邮件发送模块smtp使用详解
    下一条:
    django Admin文档生成器使用详解
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Filament v3.1版本发布(0个评论)
    • docker + gitea搭建一个git服务器流程步骤(0个评论)
    • websocket的三种架构方式使用优缺点浅析(0个评论)
    • ubuntu20.4系统中宿主机安装nginx服务,docker容器中安装php8.2实现运行laravel10框架网站(0个评论)
    • phpstudy_pro(小皮面板)中安装最新php8.2.9版本流程步骤(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2018-05
    • 2020-02
    • 2020-03
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-11
    • 2021-03
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-01
    • 2022-02
    • 2022-03
    • 2022-08
    • 2023-08
    • 2023-10
    • 2023-12
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客