drf学习-11

一、昨日回顾

1、cookie、session、token发展史

  -cookie是存在于客户端浏览器的键值对

  -session是存在于服务端的键值对,django-session,文件中、内存中、缓存中

  -token:三段式:头、荷载、签名,后端就不存储了,通过代码校验token是否合法

    -头:公司信息等

    -荷载:真正的数据

    -签名:头和荷载加密得到的

jwt(json、web、token):web方向的token,本质就是token

session认证机制的执行流程

token的认证机制

集群和分布式的区别

  -同一个业务部署在多台机器上,提高系统可用性,称之为集群

  -同的业务模块部署在不同的服务器上或者同一个业务模块分拆多个子业务,部署在不同的服务器上称之为分布式

总结:

  分布式是将不同的业务分布在不同的地方

  而集群指的是将几台服务器集中在一起,实现同一业务

2、base64编码和解码

  -网络中传输字符串

  -jwt签发

  -网络中传图片

jwt开发重点:签发(登录),认证(认证类)

django+drf中快速使用jwt 签发和认证

  -djangorestframework-jwt   旧版

  -djangorestframework-simplejwt  新版

快速签发和认证

  -签发:路由中加一个url——写了一个登录类,post方法,基于auth的user表签发的

  -认证:在视图类上:jwt提供的认证类+drf内置的权限类

重新定义签发格式

  -写一个函数,配置文件配置一下

自定义用户表,签发token

  -登录接口:有了用户对象(user)——token串——两个函数:通过user得到payload,通过payload得到token

二、今日内容

1、排序和过滤源码分析

继承了GenericAPIView+ListModelMixin,只要在视图类中配置

filter_backends它就能实现过滤和排序

  -drf内置的过滤类(SearchFilter),排序类(OrderingFiler)

  -django-filter

  -自定义:写一个类,继承BaseFilterBackend,重写filter_queryset,返回的qs对象,就是过滤或排序后的

只有获取所有才涉及到排序

  -list方法

def list(self,request,*args,**kwargs):
    # self.get_queryset()所有数据,经过了self.filter_queryset返回了qs
    # self.filter_queryset完成的过滤
    quertset = self.filter_query_set(self.get_queryset())
    # 如果有分页,走的分页——视图类中配置了分页类
    page = self.paginate_queryset(queryset)
    if page is not None:
        serializer = self.get_serializer(page,many=True)
        return self.get_paginated_response(serializer.data)
    # 如果没有分页,走正常的序列化,返回
    serializer = self.get_serializer(queryset,many=True)
    return Response(serializer.data)

-self.filter_queryset完成了过滤,当前在试图类中,self是视图类的对象,去视图类中找没找到,去父类——GeneriacAPIView——filter_queryset
    def filter_queryset(self,queryset):
        for backend in list(self.filter_backends):
            queryset = backend().filter_queryset(self.request,queryset,self)
        return queryset
        

总结:

  写的过滤类要重写filter_queryset,返回qs(过滤或排序后)对象

  后期如果不写过滤类,只要在视图类中重写filter_queryset,在里面实现过滤也可以

2、基于jwt的认证类

class JWTAuthenticaion(BaseAuthentication):
    def authenticate(self,request):
        # 放到投中:token——HTTP_TOKEN  Authorization——HTTP_AUTHOEIZATION
        print(request.META)
        jwt_value = request.MRTA.get('HTTP_TOKEN')
        # 验证token是否合法,jwt模块下一定有个验证token的函数
              try:
            payload = jwt_decode_handler(jwt_value)
        except jwt.ExpiredSignature:
            raise AuthenticationFailed('token过期了')
        except jwt.DecodeError:
            raise AuthenticationFailed('token解码失败')
        except jwt.InvalidTokenError:
            raise AuthenticationFailed('认证失败')
        # 执行到这,说明token合法,payload可以使用
        user_id = payload.get('user_id')
        user = UserInfo.objects.filter(pk=user_id).first()  # 每次都要查数据库,效率不太好
        return (user, jwt_value)
        # return (payload,jwt_value)

3、RBAC的介绍和使用

RBAC是基于角色的访问控制(Role-Based Access Control)  在RBAC中

  -权限与角色相关联,用户通过称为适当角色的成员而得到这些角色的权限。

  这就极大的简化了权限的管理。这样管理都是层级相互依赖的,权限赋予角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便

RBAC权限管理的模式,最适合公司内部的管理系统,不适合对外互联网用户的系统

  -用户:用户表

  -角色(部门):角色表(部门表)

  -权限:权限表

所有权限都是存在权限表中的一条条的记录(发工资、招聘员工、开员工、发布新版本、开董事会)

权限是授予角色的(部门的),一个个角色,就是一条条记录(开发角色,HR角色,股东角色)

用户:一个个用户是用户表中一条条记录,用户属于某个部门

三个表之间的关系

  -用户和角色关系:多对多,中间表

  -角色和权限关系:多对多,中间表

现在有5张表了

  -用户表

  -角色表

  -权限表

  -用户和角色关联表

  -角色和权限关联表

用户表:
id   姓名
1    张三
2    李四

角色表:
id    角色名称
1     HR角色
2     股东角色
3     开发角色

权限表
id    权限名词
1     发工资
2     招人
3     提交代码

-------张三要提交代码的权限---------
用户和角色中间表:
id    角色id    用户id
1     3         1

权限和角色的中间表:
id    角色id    权限id
1     3         3

django的后台管理admin就自带了rbac的权限,通过了auth模块实现的,比普通rbac更高级一些
    -本来5张表
    -django是6张表,用户和权限的多对多关系表(1个用户可以分配多个权限,一个权限可以给多个用户)
        -6张表
            -用户表
            -角色表
            -权限表
            -用户和角色关联表
            -角色和权限关联表
            -用户和权限的多对多关系表
启用了admin和auth,这6张表就迁移进去了
    auth_user # 用户表
    auth_group #角色,组,部门表
    auth_permission # 权限表
    auth_user_groups # 用户和角色中间表
    auth_group_permissions # 角色跟权限中间表
    auth_user_user_permissions # 用户和权限的中间表
 之前很多公司写后台管理使用django,使用django的admin二次开发,不用写权限了,快速加功能即可
-体验django admin的rabc的权限控制

4、ACL、RBAC、ABAC(PBAC、CBAC)权限控制的介绍

ACL(Access Control List,访问控制列表)

  将用户或组等使用者直接与对象的权限对接

  -用户表、权限表、中间   给用户授予某些权限即可

RBAC(Role-Based Access Control,基于角色的访问控制)

  将用户与角色对接,然后角色与对象的权限对接

RBAC+ACL django,公司用的比较多

ABAC(Attribute-Based Access Control,基于属性的访问控制)

ABAC(Attribute-Based Access Control,基于属性的访问控制)
又称为PBAC(Policy-Based Access Control,基于策略的访问控制)
CBAC(Claims-Based Access Control,基于声明的访问控制)

传统的ACL、RBAC的架构是
{subject,action,object},
而ABAC的架构是
{subject,action,object,contextual}且为他们添加了parameter(参数)。

subject属性:比如用户的年龄、部门、角色、威望、积分等主题属性。

action属性:比如查看、读取、编辑、删除等行为属性。

object属性:比如银行账户、文章、评论等对象或资源属性。

contextual属性:比如时段、IP位置、天气等环境属性。

权限表
id    权限表
1     开除员工

id    权限名    属性
1     开除员工  女
1     开除员工  男

方便我们快速做权限控制(acl,rbac。。。)

import casbin

e = casbin.Enforcer("./model.conf", "./policy.csv")

sub = "curry"  # 想要访问资源的用户
obj = "book"  # 将要被访问的资源
act = "get"  # 用户对资源进行的操作


# 自己写acl的控制
# 当前用户id,去权限和用户表查询即可,有记录就是有权限

# 自己写rbac
# 当前用户id,找到他的角色,根据角色拿出权限,判断当前访问有没有


if e.enforce(sub, obj, act):
    # 允许alice读取data1
    print('有权限')
else:
    # 拒绝请求,抛出异常
    print('没有权限')

model.conf

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

policy.csv

p,alice,data1,read
p,bob,data2,write
p,curry,book,get

 5、后台管理simplui的介绍和使用

django admin自带了权限控制,但是是前后端混合的,我们可以二次开发,开发出公司内部的自动化运行,自动化测试,人事管理系统,订单系统
对django admin进行美化
    -xadmin(不用了,过时了)
    -simpleui(当红炸子鸡)

基于drf+vue 自己写前后端分离的权限管理
go-vue-admin  使用simpleui

 settings.py 

import time

SIMPLEUI_CONFIG = {
    'system_keep': False,
    'menu_display': ['我的首页', '图书管理','权限认证', '多级菜单测试', '动态菜单测试'],  # 开启排序和过滤功能, 不填此字段为默认排序和全部显示, 空列表[] 为全部不显示.
    'dynamic': True,  # 设置是否开启动态菜单, 默认为False. 如果开启, 则会在每次用户登陆时动态展示菜单内容
    'menus': [
        {
            'name': '我的首页',
            'icon': 'fas fa-code',
            'url': '/index/',

        },
        {
            'app': 'app01',
            'name': '图书管理',
            'icon': 'fas fa-code',
            'models': [
                {
                    'name': '用户',
                    'icon': 'fa fa-user',
                    'url': 'app01/userinfo/'
                },
                {
                    'name': '图书',
                    'icon': 'fa fa-user',
                    'url': 'app01/book/'
                },
                {
                    'name': '出版社',
                    'icon': 'fa fa-user',
                    'url': 'app01/publish/'
                },
            ]
        },
        {
            'app': 'auth',
            'name': '权限认证',
            'icon': 'fas fa-user-shield',
            'models': [{
                'name': '用户',
                'icon': 'fa fa-user',
                'url': 'auth/user/'
            }]
        },
        {
            # 自2021.02.01+ 支持多级菜单,models 为子菜单名
            'name': '多级菜单测试',
            'icon': 'fa fa-file',
            # 二级菜单
            'models': [
                {
                    'name': '百度',
                    'icon': 'far fa-surprise',
                    # 第三级菜单 ,
                    'models': [
                        {
                            'name': '爱奇艺',
                            'url': 'https://www.iqiyi.com/dianshiju/'
                            # 第四级就不支持了,element只支持了3级
                        },
                        {
                            'name': '百度问答',
                            'icon': 'far fa-surprise',
                            'url': 'https://zhidao.baidu.com/'
                        }
                    ]
                },
                {
                    'name': 'lqz',
                    'url': 'https://www.wezoz.com',
                    'icon': 'fab fa-github'
                }]
        },
        {
            'name': '动态菜单测试',
            'icon': 'fa fa-desktop',
            'models': [{
                'name': time.time(),
                'url': 'http://baidu.com',
                'icon': 'far fa-surprise'
            }]
        }]
}


SIMPLEUI_LOGIN_PARTICLES = False
SIMPLEUI_HOME_INFO = False

 admin.py

 

from django.contrib import admin

# Register your models here.

from .models import *


@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    list_display = ('id', 'title', 'price')

    # 增加自定义按钮
    actions = ['make_copy', ]
    def make_copy(self, request, queryset):
        print('adsfasdf')
    make_copy.short_description = '自定义按钮'
    # # icon,参考element-ui icon与https://fontawesome.com
    make_copy.icon = 'fas fa-audio-description'
    # # 指定element-ui的按钮类型,参考https://element.eleme.cn/#/zh-CN/component/button
    make_copy.type = 'danger'
    make_copy.confirm = '你是否执意要点击这个按钮?'



admin.site.register(UserInfo)
admin.site.register(Publish)
posted @   初学者-11  阅读(67)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示