Django来敲门升级版--[扩展篇]--认证authenticate

Django默认提供了自己的身份认证系统,默认配置下提供有封装好的简单的用户类型以供开发人员直接使用

1. 用户类型:User

User类型是封装在django.contrib.auth.models模块下的一个内建类型,是身份认证的核心类型之一,其主要属性如下:

  • Usrename:账号
  • Password:密码
  • Email:邮箱
  • First_name:姓名
  • Last_name:姓名

1.1. 创建普通用户

内建用户直接通过类型进行创建用户的操作,如下:

from django.contrib.auth.models import User

user = User.objects.create_user(‘account’, ‘account@email.com’, ‘password’)

user.save()

1.2. 创建超级用户

Django的身份认证系统同样包含了后台管理员身份的操作,创建后台管理员账号如下

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

1.3. 修改用户密码

和常规对象的操作一致,查询并且更改用户密码,通过Django内建方法进行操作

from django.contrib.auth.models import User

user = User.objects.get(username=’account’)
user.set_password(‘new_password’)
user.save()

当然如果你已经有了后台管理员用户的话,同样可以在登录后台管理系统之后再管理界面中直接进行修改。

1.4. 用户身份认证

authenticate(request=None, **credentials) 使用authenticate()函数进行用户身份信息的验证操作,默认情况下通过关键字参数username和password进行后台认证操作,如果认证通过的情况下会返回一个认证通过的用户对象,否则返回None

from django.contrib.auth import authenticate

user = authenticate(username=’account’, password=’123123’)

if user is not None:
    # 认证通过
else:
    # 认证未通过

1.5. 权限操作和认证系统

Django为web应用的权限控制提供了一套内建的权限管理系统,可以很方便的进行用户或者用户组权限的管理和认证操作

可以通过后台管理系统直接进行操作,同样的,开发人员可以通过编码的方式进行处理。 类似于Django后台系统中定义的权限访问方式如下:

  • 访问视图中的’add’表单处理函数并且尝试添加一个对象的情况下,至少需要一个对该对象操作的’add’权限才可以
  • 访问视图中的’change’处理函数,并且尝试进行对象数据更新的情况下,至少需要一个对该对象操作 ‘change’权限才可以
  • 访问视图中的’delete’处理函数并尝试删除一个对象时,至少需要一个该对象的’delete’权限才可以

权限的设置不仅仅可以指定在类型上,同样也可以直接指定到某个对象上进行操作,通过内建的操作函数has_add_permission()、has_change_permission()以及前面提到过的has_delete_permission()进行操作,他们同样可以指定给相同类型的不同对象上。

内建用户对象有两个多对多的字段,分别是group和user_permission,内建用户对象可以通过内建方法很方便的进行用户组的操作和权限的操作

# 用户组操作
myuser.groups.set([group_list])
myuser.groups.add(group1, group2..)
myuser.groups.remove(group1, group2..)
myuser.groups.clear()

# 权限的操作
myuser.user_permission.set([permission_list])
myuser.user_permission.add(perm1, perm2..)
myuser.user_permission.remove(perm1, perm2..)
myuser.user_permission.clear()

1.6. 默认权限操作

当django.contrib.auth出现在你项目配置文件的INSTALLED_APPS列表中时,系统就会默认附带三个权限[add/change/delete]的操作了,可以在你安装的每个子模块应用中使用这些权限。

默认情况下,当我们在项目中执行数据库操作migrate时,添加在INSTALLED_APPS列表中的权限认证模块django.contrib.auth需要的数据都会被执行到数据库中,并添加对应的默认权限操作。

此时如果我们有一个应用并在应用foo中有一个数据模型Bar,使用它的默认权限如下:

  • add:user.has_perm(‘foo.add_bar’)
  • change: user.has_perm(‘foo.change_bar’)
  • delete: user.has_perm(‘foo.delete’)

1.7. 编程实现权限操作

假设我们在自己的模块应用blog中定义了一个类型Article,可以在程序中通过如下的方式添加一个’publish’发布的权限

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

from . import models

content_type = ContentType.objects.get_for_model(models.Aritlce)

    permission = Permission.objects.create(
    codename=‘publish’,
    name=’can publish articles’,
    content_type=content_type
)

此时就是给指定的类型创建了一个权限对象,这个权限就可以通过user_permission字段添加给指定的某个用户或者用户组了。

1.8. 权限缓存

Django的模型操作后台管理代码中对于权限的检查操作进行了缓存处理,任何对象在进行权限检查操作过程中都会针对当前检查的权限进行缓存操作,即使在中途我们针对某个权限进行了更新操作,但是执行权限检查的结果还是缓存的结果。这个问题最直接的解决方案就是如果进行了权限更新的话,为了不受缓存数据的影响,直接从数据库中重新获取用户数据即可!

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

from myapp.modles import Article

def user_gains_perms(request, user_id):
# 获取一个用户对象
user = get_object_or_404(User, pk=user_id)
# 检查权限:注意~此时检查权限的结果会被缓存起来
user.has_perm(‘myapp.change_article’) # False

# 获取change_article权限对象
content_type = ContentType.objects.get_for_model(Article)
permission = Permission.objects.get(
    code_name=’change_article’,
    content_type=content_type
)
# 添加权限给用户
user.user_permission(permission)

# 检查权限:得到缓存的结果~但是此时结果是错误的
user.has_perm(‘myapp.change_article’)   # False

# 重新获取对象数据
user = get_object_or_404(User, pk=user_id)
# 检查权限,得到正确的结果
user.has_perm(‘myapp.change_article’)  # True

#### 1.9.   web请求认证
Django通过session对象和内建中间件组件进行请求request的认证管理操作

项目中每个请求都会附带一个request.user这样的属性数据,如果用户没有登录的情况下会自动赋值一个匿名用户[AnonymousUser],否则就返回当前登录用户,主要通过如下的方式进行操作:
if requeset.user.is_authenticated:
        # 认证通过的登录用户
else:
        # 认证不通过的匿名用户
1.9.1. 登录操作

如果你已经有了可以登录的用户账号,并且想通过这个账号进行系统登录操作的话,可以通过login()函数进行处理

login(request, user, backends=None) 函数主要进行用户的登录操作,需要一个请求对象requset参数和一个用户对象user参数进行操作,login()会将登录的用户信息自动记录到session中。

以下是一个验证和登录合并的案例操作:

from django.contrib.auth import authenticate, login

def my_view(request):
username = request.POST[‘username’]
password = request.POST[‘password’]

# 认证操作
user = authenticate(request, username=username, password=password)
if user is not None:
        # 登录操作,自动记录数据到session
        login(request, user)
else:
        # 没有认证成功
1.9.2. 登出操作

可以登录系统,当然可以进行安全退出系统的操作,Django封装内建了logout()函数主要实现该功能操作

logout(request) 执行一个登出操作,将通过django.contrib.auth.login()函数添加的用户信息从系统中移除,logout()函数需要一个HttpRequest请求对象参数,无返回值。

from django.contrib.auth import logout

def logout_view(request):
    logout(request)
    # 重定向到下一个页面
1.9.3. 登录失败操作

在实际项目操作过程中,需要用户身份认证才能访问的函数的正确作法推荐两种,一种是认证失败时跳转到登录页面,但是要附带当前路径信息,方便用户登录成功以后直接跳转到正在访问的页面,另一种直接跳转错误页面即可

  • 认证失败跳转登录页面
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’)
1.9.4. 登录认证装饰器

Django提供了内置封装的装饰器进行登录认证操作,认证失败时自动跳转到项目配置文件指向的LOGIN_URL路径

from django.contrib.decorators import login_required

@login_required
def my_view(request):
    pass

或者直接可以在装饰器上指定跳转到认证页面的配置

from django.contrib.decorators import login_required

@login_required(login_url=’/blog/login/’)
def my_view(request):
    pass
1.9.5. 权限认证装饰器

permission_require(perm, login_url=None, raise_exception=False) 权限认证装饰器通过快捷的权限验证操作,可以很方便的控制用户访问对应的视图处理函数的操作

from django.contrib.decorators import permission_required

@permission_required(‘blog.can_comment’)
def my_view(request):
    pass

和权限检查函数has_perm()一样,可以通过<app label>.<permission.codename>的方式进行认证操作,如果用户没有对应的访问权限操作的话,会自动抛出403禁止访问的异常信息,主要是PermissionDenied权限未定义的错误导致的禁止访问!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏微信公众号:Java团长

互联网协议入门(二)

这是从设计者的角度看问题,今天我想切换到用户的角度,看看用户是如何从上至下,与这些协议互动的。

8320
来自专栏python3

python3--threading模块(线程)

程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态...

54620
来自专栏软件工程师成长笔记

进程与线程的联系和区别?

74420
来自专栏坚毅的PHP

使用 Java Service Wrapper 启动java后台进程服务

 Java Service Wrapper (http://wrapper.tanukisoftware.com/doc/english/product-ove...

52250
来自专栏java思维导图

互联网协议入门(二)

技术文章第一时间送达! 本文来自“阮一峰的网络日志” 上一篇文章分析了互联网的总体构思,从下至上,每一层协议的设计思想。 这是从设计者的角度看问题,今天我想切换...

27780
来自专栏决胜机器学习

Redis专题(一)——Redis基本概述与安装配置

Redis专题(一) ——Redis基本概述与安装配置 (原创内容,转载请注明来源,谢谢) 一、特性 1、存储方式 Redis采用Key-Va...

33140
来自专栏玄魂工作室

Hacker基础之Linux篇:基础Linux命令一

这一部分主要是讲解Linux常用命令工具,比如文件管理,文本处理等等,主要是为了让读者用最少的实践掌握和熟练应用基本的Linux操作,对于每个命令的举例,尽量做...

30070
来自专栏IT笔记

Linux下用户组、文件权限详解

用户组 在linux中的每个用户必须属于一个组,不能独立于组外。在linux中每个文件有所有者、所在组、其它组的概念 所有者 所在组 其它组 改变用户所在的组 ...

37740
来自专栏Java技术分享圈

杨老师课堂之JavaEE三大框架Struts2入门第一课

...

7630
来自专栏小狼的世界

Linux中的Diff和Patch

本文主要记录两个命令的学习情况:diff 和 patch。diff 和 patch 是一对工具,使用这对工具可以获取更新文件与历史文件的差异,并将更新应用到历史...

18730

扫码关注云+社区

领取腾讯云代金券