$Django Rest Framework-认证组件,权限组件 知识点回顾choices,on_delete

时间:2023-03-09 10:04:43
$Django Rest Framework-认证组件,权限组件 知识点回顾choices,on_delete

一 小知识点回顾

#orm
class UserInfo (models.Model):
id = models.AutoField (primary_key=True)
name = models.CharField (max_length=32)
pwd = models.CharField (max_length=32)
choices = ((0, '普通用户'), (1, 'vip用户'), (2, '年费vip'))
user_type = models.IntegerField (choices=choices, default=0)
#view
获取汉字
request.user.get_user_type_display()

choices

class Book (models.Model):
# 表示外键关联到出版社表,当出版社表删除了该条数据,图书表中不删除,仅仅是把外键置空
# 同时存在null=True,on_delete=models.SET_NULL
publish = models.ForeignKey (to='Publish', to_field='id', null=True, on_delete=models.SET_NULL)

dj2必须写on_delete,dj1默认models.CASCADE

二 认证组件

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import APIException
from app01 import models
from app01.get_token import get_token
class Auth(BaseAuthentication):
def authenticate(self,request):
token=request.query_params.get('token')
#存数据库的token
# ret=models.UserToken.objects.filter(token=token).first()
# 不用存的token
if token:
user_id=token.split('|')[1]
token_=token.split('|')[0]
ret=get_token(user_id)
if ret==token_:
# return ret.user,ret
user = models.UserInfo.objects.filter (id=user_id).first ()
return user,user
else:
raise APIException('你还没有登陆')
else:
raise APIException ('你还没有登陆')

认证组件重点authenticate(self,request)返回元组(request.user,request.auth)或者异常

#局部使用
class Login(APIView):
authentication_classes=[Auth,]
def post(self,request):
pass #全局使用 settings里面配置
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ['app01.Myauthentication.Auth',],
}
class Login(APIView):
#局部禁用认证组件
authentication_classes=[]
def post(self,request):
pass

局部使用,全局使用(局部禁用)

import hashlib
import time
def get_token(xxx):
# 存数据库的token
# md5=hashlib.md5()
# md5.update(xxx.encode('utf-8'))
# md5.update(str(time.time()).encode('utf-8'))
#不存数据库的token
md5=hashlib.md5()
md5.update('天王盖地虎xx蘑菇炖小鸡'.encode('utf-8'))
md5.update(str(xxx).encode('utf-8'))
md5.update('自古英雄爱美人'.encode('utf-8'))
return md5.hexdigest() class Login(APIView):
#局部禁用认证组件,setting定义全局
authentication_classes=[]
#局部使用认证组件
#authentication_classes=[Auth,]
def post(self,request):
name=request.data.get('name')
pwd=request.data.get('pwd')
response={'status':100,'msg':'登陆成功'}
try:
ret=models.UserInfo.objects.get(name=name,pwd=pwd)
# 存数据库的token
# token = get_token (ret.name)
# models.UserToken.objects.update_or_create(user=ret,defaults={'token':token})
# 不用存的token
token = get_token (ret.id)
response['token']='{}|{}'.format(token,ret.id)
except ObjectDoesNotExist:
response['status']=101
response['msg']='用户名或密码不存在'
except Exception:
response['status'] = 102
response['msg'] = '未知错误'
return JsonResponse(response,safe=False)

Login

三 权限组件(认证组件通过后可以拿到request.user)

from rest_framework.permissions import BasePermission

class Per(BasePermission):
message='请先升级用户'
def has_permission(self,request,view):
user_type=request.user.user_type
if user_type==1:
return True
return False

权限组件重点has_permission(self,request,view)判断权限字段为vip返回False,不足返回True.message='请先升级用户'

#1局部使用
class Books(APIView):
permission_classes=[Per,]
def get(self,request):
response={'status':100,'msg':'请求成功'}
books=models.Book.objects.all()
ser=Myserializers.Books(books,many=True)
response['data']=ser.data
return JsonResponse(response,safe=False) #2全局使用 settings里配置
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ['app01.Myauthentication.Auth',],
'DEFAULT_PERMISSION_CLASSES': ['app01.Mypermission.Per', ]
}
#配置好了全局默认使用
class Books(APIView):
def get(self,request):
response={'status':100,'msg':'请求成功'}
books=models.Book.objects.all()
ser=Myserializers.Books(books,many=True)
response['data']=ser.data
return JsonResponse(response,safe=False) #局部禁用
class Books(APIView):
permission_classes=[]
def get(self,request):
response={'status':100,'msg':'请求成功'}
books=models.Book.objects.all()
ser=Myserializers.Books(books,many=True)
response['data']=ser.data
return JsonResponse(response,safe=False)

局部使用,全局使用(局部禁用)

源码剖析

#一 Apiview的dispach方法
把Apiview的认证列表 封装进了request对象里 #二 Apiview执行认证方法
#self.perform_authentication(request)
def perform_authentication(self, request):
request.user #调用了user方法 #三 request.user方法
@property
def user(self):
if not hasattr(self, '_user'):
with wrap_attributeerrors():
self._authenticate()
return self._user #四 self._authenticate()
def _authenticate(self):
for authenticator in self.authenticators:
try:
user_auth_tuple = authenticator.authenticate(self)
except exceptions.APIException:
self._not_authenticated()
raise if user_auth_tuple is not None:
self._authenticator = authenticator
self.user, self.auth = user_auth_tuple
return self._not_authenticated()

认证分析

#一 Apiview的self.check_permissions(request)方法
# self.get_permissions()为Apiview的权限对象列表
def check_permissions(self, request):
for permission in self.get_permissions():
if not permission.has_permission(request, self):
self.permission_denied(
request, message=getattr(permission, 'message', None)
)

权限分析

认证组件源码实现方式

总结:  as_view()闭包函数如返回view的内存地址 ,内部的view返回dispach的执行结果

1->apiview的as_view() 重用view的as_view() 返回了一个

csrf_exempt(view)

2->apiview自己的dispach方法内

(重新包装request,调用了认证【返回request.user】权限频率方法,判断reques.method 在没在 view类下的请求方式列表内 )

返回request.method.请求方式()/抛出异常执行结果执行

3->apiview定义了

authentication_classes地址列表 执行了自己的方法
authenticators=self.get_authenticators()拿到一个个对象列表
传入request类生对象
4—>requst.user
再request类中
for循环列表对象
调了列表对象类的
ret=authenticator.authenticate(self) #self为request对象
return self.user,self.auth




随机推荐

  1. Golang入门教程(八)复合数据类型使用案例一

    目录 数组 指针 结构体(struct) 一.数组 Go 语言提供了数组类型的数据结构. 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形.字符串或者自定 ...

  2. 细说shiro之五:在spring框架中集成shiro

    官网:https://shiro.apache.org/ 1. 下载在Maven项目中的依赖配置如下: <!-- shiro配置 --> <dependency> <gr ...

  3. 魔改版BBR

    魔改版bbr加速: wget -N --no-check-certificate "https://raw.githubusercontent.com/chiakge/Linux-NetSp ...

  4. XOR 加密

    XOR 是一个神奇的运算符, 观察它的真值表, 很容易得到以下结论: 假设现有 a , b 变量, 则 a ^ 0 == a a ^ 0xff == ~a (取反加1等于作为补码的a的真值的相反数的补 ...

  5. VS Code使用 Vue工程配置 eslint

    首先确保VS Code 安装了 Vetur 和 Eslint 插件. VS CODE :文件 =>首选项 => 设置   (有3个点 或 {} 这样的大括号,打开setting.json) ...

  6. js 数组拷贝与深拷贝

    1.对于普通数组(数组元素为数字或者字符串) var _testCopy = [1,2,3].concat();//拷贝数组(浅拷贝) 2.对于对象数组 (深拷贝) //形如var _objArr=[ ...

  7. Jrebel for Android 安装使用

    1.打开File-Setting-plugin-browse repositories.然后点击Manger repositories添加我们的私人存储库 http://dl.zeroturnarou ...

  8. Python安全 - 从SSRF到命令执行*

    前两天遇到的一个问题,起源是在某个数据包里看到url=这个关键字,当时第一想到会不会有SSRF漏洞. 以前乌云上有很多从SSRF打到内网并执行命令的案例,比如有通过SSRF+S2-016漏洞漫游内网的 ...

  9. luogu P4314 CPU监控

    传送门 这是个远古巨坑阿qwq 没有历史最大值还是能比较好做的.可能会有一个想法,就是直接维护线段树每个结点出现过的历史最大值,每次最大值变化就更新.但是有个问题:可能一个点能影响历史最大值的标记还没 ...

  10. Tomcat清理日志文件无法立即释放磁盘空间

    1 自己删除了Tomcat的日志文件,但是依然显示磁盘百分百占用 进入Tomcat目录显示日志已经删除 查询磁盘空间依旧百分百占用 2 自己杀死Tomcat进程然后重启,成功释放空间 3 原因,通过网 ...