# 研究simple-jwt提供的Token类:
????????1、RefreshToken:生成refresh token的类
? ? ? ? 2、AccessToken:生成refresh token的类
? ? ????3、Token:他们俩的父类
? ??????4、str(RefreshToken的对象)---得到字符串 refresh token,Token类写了 __str__
????????5、str(RefreshToken的对象.access_token)---得到字符串 access token,Token类写了 __str__,RefreshToken类中access_token是方法被包装成了数据属性,返回值是AccessToken的对象
????????6、RefreshToken,AccessToken的对象,都能点出 payload 荷载
????????7、RefreshToken,AccessToken的对象,都能通过中括号取出荷载中得值# 魔法方法之 . 操作:
?? 点拦截:?__getattr__、__setattr__
? ?对象.name? ? ? ? 当name不存在就会触发__getattr__执行
? ?对象.name='xxx'? ? ? ? ? ? 触发__setattr__# 魔法方法之 [ ] 操作:
?? ?[ ] 拦截:__getitem__、__setitem__
? ? 对象['name']? ? ? ? ? ?当name不存在 ?触发__getitem__执行
? ? 对象['name']='xxx'? ? ? ? ? ? ? ? 触发__setitem__
#?自定义表签发token步骤:
????????1、快速签发和认证
????????2、定制返回格式和认证
????????3、自定义登录和认证,自定义表,自定义认证类# 视图类: from rest_framework.decorators import action from rest_framework.viewsets import GenericViewSet from rest_framework.response import Response from .serializer import LoginSerializer class UserView(GenericViewSet): serializer_class = LoginSerializer # 127.0.0.1:8000/api/v1/user/login/ @action(methods=['POST'], detail=False) def login(self, request): ser = self.get_serializer(data=request.data) ser.is_valid(raise_exception=True) return Response(ser.validated_data)
# 序列化类: from rest_framework import serializers from .models import UserInfo from rest_framework.exceptions import APIException from rest_framework_simplejwt.tokens import RefreshToken class LoginSerializer(serializers.Serializer): username = serializers.CharField() password = serializers.CharField() def validate(self, attrs): # 只做校验 username = attrs.get('username') password = attrs.get('password') user = UserInfo.objects.filter(username=username, password=password).first() if user: # 签发token,使用RefreshToken直接签发 refresh = RefreshToken.for_user(user) return { 'code': 100, 'msg': '登录成功', 'username': username, # 'icon':user.icon, 'access': str(refresh.access_token), 'refresh': str(refresh) } else: raise APIException({'code': 999, '101': '用户名或密码错误'})
# 表模型: class UserInfo(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=32) age = models.IntegerField() gender = models.IntegerField(choices=((1, '男'), (2, '女'), (0, '未知')))
# 总路由: from django.contrib import admin from django.urls import path,include urlpatterns = [ path('admin/', admin.site.urls), path('app/', include('app01.urls')), ] # app01路由 from rest_framework.routers import SimpleRouter from .views import UserView router = SimpleRouter() router.register('user', UserView, 'user') urlpatterns = [ ] urlpatterns += router.urls
# 视图层: from rest_framework.viewsets import GenericViewSet from rest_framework.response import Response from .auth import LoginAuthentication class BookView(GenericViewSet): # 自定义用户表,使用JWTAuthentication无法完成验证,必须自定义认证类 # authentication classes = [JWTAuthentication] # permission_classes = [IsAuthenticated] # 自定义用户表,使用自定义认证类 authentication_classes = [LoginAuthentication] def list(self, request): print(request.user.username) return Response('好大一个家~')
# 认证类: from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import APIException from rest_framework_simplejwt.tokens import AccessToken from .models import UserInfo class LoginAuthentication(BaseAuthentication): def authenticate(self, request): token = request.META.get('HTTP_TOKEN') # 拿到token if token: # 验证token是否合法,是否过期,是否被篡改,伪造 try: validated_token = AccessToken(token) except Exception as e: raise APIException({'code':101,'msg':str(e)}) # 取出用户id,根据id查出用户并返回 # validated_token.payload['user_id'] # validated_token['user_id'] user = UserInfo.objects.filter(pk=validated_token['user_id']).first() return user,token else: raise APIException({'code': 102, 'msg': 'token必须携带
模型层: class Book(models.Model): name = models.CharField(max_length=32) price = models.IntegerField
drf 中有权限控制:
1、acl权限控制:访问控制列表 Access Control List
? ? # 互联网,对外项目
? ? # 用户可以:? ? ? ? ? ?user_id:1=[刷视频,评论,收藏,开直播] user_id:2=[刷视频]
? ? ?# 权限类:根据当前登录用户,取出它所有权限,权限列表????????????????当前访问的比如是评论,如果有权限,返回True,没有权限,返回false
2、rabc权限控制 : 基于角色的访问控制 Role-Based Access Control
?# 公司内部项目,用户属于某个角色,角色跟权限有对应关系:
? ? ? ? ?? ?*财务:张三、李四----发工资权限,扣工资权限
? ? ? ? ? ? *hr: ?王铁锤、王五----招员工,开除员工
? ? ? ? ? ? *开发:张二蛋、李小红----看代码 开发代码,删除代码
? ? ? ? ? ? *总裁:zjq----查看公司财报
?# rbac表设计:
? ? ? ? ????????用户表:用户和角色是 ? ?多对多
? ? ? ? ? ? ? ? 角色表(部门,组): 角色和权限 ?多对多
? ? ? ? ? ? ? ? 权限表:用户和权限:多对多
? ? ? ?总共6 张表,表示基于角色的访问控制:rbac+acl
?# django的后台管理就是基于rbac控制---auth下有些表:? ? ? ? ? ? ? ??auth_user:# 用户表 auth_group:# 组表(角色) auth_permission:# 权限表 auth_group_permissions # 组和权限中间表 auth_user_groups # 用户和组 中间表 auth_user_user_permissions# 用户和权限多对多中间表
?# 演示rbac权限控制:
? ? ? ?创建一个超级用户 root ?123456 对网站有所有权限
? ? ? ?创建一个用户[张三],创建一个组[测试组1],给测试组1加权限[book的增删查改]
? ? ? ?张三登录,发现张三有 测试组1的所有权限
? ? ? ?新增用户李四,没有任何组,登录后没有任何权限
? ? ? ?把李四放到 测试组1 ,有测试组1的所有权限:查看图书,修改图书,删除图书
? ? ? ? 李四增加一个新增图书权限:
? ? ? ? ? ? ? ? ? ? 新增图书权限 加入到 测试组1 ?张三也有这个权限,不好
? ? ? ? ? ? ? ? ? ? 单独给李四增加一个 新增图书权限?
3、ABAC:Attribute-Based Access Control,基于属性的访问控制? ? ? ?
? ?# 公司内部项目,所有项目几乎都要有rbac权限
?? # 基于django的admin做二次开发,美化页面,混合
? ?# django+vue,实现基于rbac的访问控制
? ? ? ? ? ? ? ? django:django-vue-admin
? ? ? ? ? ? ? ? go:gin-vue-admin
? ? ? ????????? java:若依
所有接口一分钟只能访问5次
需求:任务管理系统
1.创建一个表,包括任务标题(title) 、任务描述(description) 、任务截止日期(deadline) ,任务开始时间(stattime),任务状态(status)
2.写接口,允许用户列出所有任务、查看单个任务详情、创建新任务、更新现有任务和删除任务。
?? ?-查询所有:
? ? -查询单条
? ? -创建一条
? ? -更新一条
? ? -删除一条
3.实现分页功能,每页显示10条任务记录,可以使用size控制再多显示,但是最多不超过20条
4.添加任务搜索功能,用户可以通过任务标题或任务描述搜索任务。
?? ?-自定义
5.将任务状态分为"待办"、"进行中"和"已完成",用户可以根据任务状态筛选任务。
?? ?-choice字段
? ? -过滤 status=2
? ? -使用djagno-filter
6 可以按任务开始时间排序
?? ?-自定义,使用内置的
?
7 自定义用户表,token表:username,password,age,active,usertype字段字段
8 写个登录,如果是active是false不允许登录
9 任务查询所有和查询单条接口,不需要登录就能访问
10 创建,更新和删除,必须登录才能操作
10 任务创建和更新,普通用户就可以操作
11 任务删除功能,只能超级管理员操作
12 超级管理员能锁定和解锁用户
?? ?post请求:127.0.0.1:8080/ap1/v1/users/1/lock
? ? 请求中携带 {lock:true/false}