IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Django——权限验证与cookie&session -> 正文阅读

[Python知识库]Django——权限验证与cookie&session

需求

创建三个页面,每个页面都有对应的访问权限,没有权限的用户是无法访问的。

一、权限

在models中:
创建apage model和b page model

# coding:utf-8
from django.db import models

class Apage(models.Model):
    title = models.CharField(max_length=10)

    def __str__(self):
        return '{}'.format(self.title)

    class Meta:
        permissions = [
            ('look_a_page', 'can get this a page message')
        ]


class Bpage(models.Model):
    title = models.CharField(max_length=10)

    def __str__(self):
        return '{}'.format(self.title)

    class Meta:
        permissions = [
            ('look_b_page', 'can get this b page message')
        ]

在templates中创建a和b两个html,
然后在views中添加这两个page

class A(View):
    TEMPLATE = 'a.html'
    
    def get(self, request):
        return render(request, self.TEMPLATE)


class B(View):
    TEMPLATE = 'b.html'

    def get(self, request):
        return render(request, self.TEMPLATE)

然后把这两个注册到路由中:

from django.urls import path
from .views import Regist, Login, LogoutUser, A, B

urlpatterns = [
    path('regist', Regist.as_view(), name='regist'),
    path('login', Login.as_view(), name='login'),
    path('logout', LogoutUser.as_view(), name='logout'),
    path('a', A.as_view(), name='a_page'),
    path('b', B.as_view(), name='b_page')
]

在这里插入图片描述
可以正常访问

{% if user.has_perm(permission) %}
欢迎访问A page
{% else %}
您无权访问
{% endif %}
class A(View):
    TEMPLATE = 'a.html'

    def get(self, request):

        if not request.user.is_authenticated:  # 如果用户没有登录,就定向到login页面
            return redirect(reverse('login'))

        a_permission = Permission.objects.get(codename='look_a_page')
        print('a')
        print(a_permission)
        print(request.user.has_perm(a_permission))

        if not request.user.has_perm(a_permission):  # 这里验证一下user是否有a权限
            print(a_permission)
            print(request.user.has_perm(a_permission))
            print('test')
            return render(request, self.TEMPLATE, {'error': '您无权访问该页面'})
        else:
            return render(request, self.TEMPLATE, {'info': '欢迎光临'})

在这里插入图片描述
我这里是有权限的。

有两个函数可以通过装饰器额方式验证

# 这两个只能使用在面向函数对象的情况下
from django.contrib.auth.decorators import login_required, permission_required


@login_required(login_url='/login')  # 如果没有登录,会自动跳转到login地址
def a(request):
    return render(request, 'a.html')

如果a没有登录,就会自动跳转到login地址。
在这里插入图片描述
这里的next表示,如果登录完成,接下来就会自动跳转到a地址。

然后对权限进行设置:
permission_required,括号里添加权限app.look_a_page,app是应用名,look_a_page是权限名。
在这里插入图片描述
如果没有权限就直接404了。

@login_required(login_url='/login')  # 如果没有登录,会自动跳转到login地址
@permission_required(perm='a.look_a_page')
def a(request):
    return render(request, 'a.html')

这两个函数login_requiredpermission_required是直接面对函数的,他们会读取request,login_required里面使用了request.user.is_authenticated验证方式,和我们之前写的如下两句话是一样的:

if not request.user.is_authenticated:  # 如果用户没有登录,就定向到login页面
        return redirect(reverse('login'))

permission_required也同样是验证request.user.has_perm(a_permission),如果没找到,就Http404。

然后我们修改一下之前的A,如果没有权限就抛出raise 404

class A(View):
    TEMPLATE = 'a.html'

    def get(self, request):

        if not request.user.is_authenticated:  # 如果用户没有登录,就定向到login页面
            return redirect(reverse('login'))

        a_permission = Permission.objects.get(codename='look_a_page')

        if not request.user.has_perm(a_permission):

            raise Http404
     
        return render(request, self.TEMPLATE)

在这里插入图片描述
就404了。

添加权限

进入shell:

>>> from django.contrib.auth.models import User, Permission
>>> a_permission = Permission.objects.get(codename='look_a_page')
>>> user = User.objects.get(username='cong')
>>> user
<User: cong>
>>> user.user_permissions.add(a_permission)

结果添加上权限后并没有验证成功。

print(request.user.user_permissions.values())

在这里插入图片描述
print一下也能看到权限存在,但是验证没有通过。

原因:user在查询时并不需要把对象传进去,而是直接传app下的权限名。

>>> user.has_perm('app.look_a_page')
True

然后我们修改一下之前的代码。

class A(View):
    TEMPLATE = 'a.html'

    def get(self, request):

        if not request.user.is_authenticated:  # 如果用户没有登录,就定向到login页面
            return redirect(reverse('login'))

        # a_permission = Permission.objects.get(codename='look_a_page')

        if not request.user.has_perm('app.look_a_page'):  # 改了这里,里面不是传a_permission
            raise Http404
        
        return render(request, self.TEMPLATE)

注意下user.has_perm('app.look_a_page')
在这里插入图片描述
现在可以正常访问了。

二、组

创建一个组,给组赋予权限,并把用户添加到组中

在shell中创建一个组。

>>> from django.contrib.auth.models import Group
>>> Group.objects.create(name='b')
<Group: b>
>>> group = Group.objects.get(name='b')
>>> group
<Group: b>

创建了一个组。

然后我们先看一下有哪些权限:

>>> from django.contrib.auth.models import Permission
>>> result = Permission.objects.all()
>>> result
<QuerySet [<Permission: admin | 日志记录 | Can add log entry>, <Permission: admin | 日志记录 | Can change log entry>, <Permission: admin | 日志记录 | Can delete log entry>, <Permission: admin | 日志记录 | Can view log entry>, <Permission: app | apage | Can add apage>, <Permission: app | apage | Can change apage>, <Permission: app | apage | Can delete apage>, <Permission: app | apage | can get this a page message>, <Permission: app | apage | Can view apage>, <Permission: app | bpage | Can add bpage>, <Permission: app | bpage | Can change bpage>, <Permission: app | bpage | Can delete bpage>, <Permission: app | bpage | can get this b page message>, <Permission: app | bpage | Can view bpage>, <Permission: auth || Can add group>, <Permission: auth || Can change group>, <Permission: auth || Can delete group>, <Permission: auth || Can view group>, <Permission: auth | 权限 | Can add permission>, <Permission: auth | 权限 | Can change permission>, '...(remaining elements truncated)...']>

很多很多。。
然后我们再去数据库中看一下
在这里插入图片描述
可以看到我们即使不添加look_a_page权限,我们在创建数据库的时候也拥有了add,change,delete,view这四个权限。
在这里插入图片描述
这个content_type_id就是因为在django_content_type表中,apage和bpage的id是7和8.

组添加权限

>>> permissions = Permission.objects.filter(content_type_id=8)
>>> permissions
<QuerySet [<Permission: app | bpage | Can add bpage>, <Permission: app | bpage | Can change bpage>, <Permission: app | bpage | Can delete bpage>, <Permission: app | bpage | can get this b page message>, <Permission: app | bpage | Can view bpage>]>
>>> for i in permissions:
...     group.permissions.add(i)
...
>>> group.permissions.values()
<QuerySet [{'id': 30, 'name': 'Can add bpage', 'content_type_id': 8, 'codename': 'add_bpage'}, {'id': 31, 'name': 'Can change bpage', 'content_type_id': 8, 'codename': 'change_bpage'}, {'id': 32, 'name': 'Can delete bpage', 'content_type_id': 8, 'codename': 'delete_bpage'}, {'id': 34, 'name': 'can get this b page message', 'content_type_id': 8, 'codename': 'look_b_page'}, {'id': 33, 'name': 'Can view bpage', 'content_type_id': 8, 'codename': 'view_bpage'}]>

可以看到组里有的这些权限。

用户添加的组里

现在我们要把用户添加到组里

>>> user.groups.add(group)
>>> user
<User: cong>
>>> user.groups.all()
<QuerySet [<Group: b>]>
>>> user.user_permissions.values()
<QuerySet [{'id': 29, 'name': 'can get this a page message', 'content_type_id': 7, 'codename': 'look_a_page'}]>

但是看一下user的权限,依旧是之前的那些权限。

现在我们先去views里给B添加一些权限

class B(View):
    TEMPLATE = 'b.html'

    def get(self, request):

        b_permission = Permission.objects.filter('look_b_page').first()

        # 用Q查询,查询组里有没有对应权限
        # 去用户的groups里面看一下,有没有b_permission,或者是user里有没有b_permission,为了防止重复,去重
        users = User.objects.filter(Q(groups_permissions=b_permission) |
                                    Q(user_permission=b_permission)).distinct()
        print(users)

        return render(request, self.TEMPLATE)

结果。。
在这里插入图片描述
原来是filter没有写codename参数b_permission = Permission.objects.filter(codename='look_b_page').first()
然后又发现一个bug,这里写的不对,要写成下面这样

users = User.objects.filter(Q(groups__permissions=b_permission) |
                                    Q(user_permissions=b_permission)).distinct()

在这里插入图片描述
然后再加一个判断:如果请求页面的用户不在users中,就404

        if request.user not in users:
            raise Http404()

在这里插入图片描述
可以进来,说明有权限。

判断用户是否登录新方法

from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required


class B(View):
    TEMPLATE = 'b.html'

    # 在第一层装饰器中把 login_required放进去,如果没有登录,就跳转到login
    # 这样login_required就可以面向对象使用了
    @method_decorator(login_required, name='login')
    def get(self, request):

然后再看如何用装饰器添加权限。

from django.contrib.auth.decorators import login_required, permission_required


class B(View):
    TEMPLATE = 'b.html'

    # 在第一层装饰器中把 login_required放进去,如果没有登录,就跳转到login
    # 这样login_required就可以面向对象使用了
    @method_decorator(login_required)
    @method_decorator(permission_required('app.look_b_page'))
    def get(self, request):

        b_permission = Permission.objects.filter(codename='look_b_page').first()

导入permission_required,然后再加上我们需要验证的权限permission_required('app.look_b_page')

总结

自定义权限:创建一个model,在model的meta里自定义权限;用户添加权限;验证用户是否拥有权限;如何创建组,给组添加权限,用户如何加入组,退出组;以及两个装饰器如何在面向函数和面向对象的方式下使用。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-11-16 18:47:09  更:2021-11-16 18:48:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 0:20:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码