drf 权限校验设置与源码分析
权限校验
权限校验和认证校验必须同时使用,并且权限校验是排在认证校验之后的,这在源码中可以查找到其执行顺序。
权限校验也很重要,认证校验可以确保一个用户登录之后才能对接口做操作,而权限校验可以依据这个登录用户的类型来限定能对接口做那些操作。
准备工作
模型表
下面是模型表,对于不同等级的用户,访问同一url,能够获取到的电影内容也不一样。
from django.db import models
# Create your models here.
class User(models.Model):
user_id = models.AutoField(primary_key=True)
user_name = models.CharField(max_length=32)
user_password = models.CharField(max_length=32)
user_type = models.IntegerField(choices=(
[0,"普通用户"],
[1,"黄金VIP"],
[2,"钻石VIP"],
))
user_token = models.CharField(max_length=64, null=True, unique=True)
class Film(models.Model):
film_id = models.AutoField(primary_key=True)
film_name = models.CharField(max_length=32)
film_grade = models.IntegerField(
choices=(
[0,"免费电影"],
[1,"黄金VIP专享"],
[2,"钻石VIP专享"]
)
)
用户表数据如下:

电影表数据如下:

序列类
采用模型类序列器,并且只对电影做序列化:
from rest_framework import serializers
from app01 import models
class FilmModelSerializers(serializers.ModelSerializer):
class Meta:
model = models.Film
fields = "__all__"
认证校验
下面是认证权限,只有登录后的用户才可以看到电影信息。如果没有登录将不允许查看所有电影的页面,或者你也可以不设置认证校验,但是在权限设置中可以设置匿名用户直接返回一个False也行。
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import APIException
from app01 import models
class LoginAuth(BaseAuthentication):
def authenticate(self,request):
token = request.META.get("HTTP_TOKEN")
if not token:
# 未登录
raise APIException("未登录,无法查看本电影网站,请先登录")
user_obj = models.User.objects.filter(user_token=token).first()
if not user_obj:
raise APIException("token无效,登录失败")
else:
return user_obj,user_obj.user_type # 将用户对象本身以及用户的类型存储到request.user以及request.auth中
视图
下面是视图的代码:
from uuid import uuid4
from rest_framework.generics import ListAPIView
from rest_framework.generics import GenericAPIView
from rest_framework.views import APIView
from rest_framework.views import Response
from app01 import models
from app01 import serializationClass
from app01 import app01_auth
class FilmAPI(ListAPIView,GenericAPIView):
authentication_classes = [app01_auth.LoginAuth] # 必须登录
queryset = models.Film.objects.all() # 默认查看所有,任何用户都是
serializer_class = serializationClass.FilmModelSerializers
def get(self,request):
return self.list(request)
class Login(APIView):
def post(self,request):
user_dict = {
"user_name":request.data.get("user_name"),
"user_password":request.data.get("user_password"),
}
user_obj = models.User.objects.filter(**user_dict).first()
if not user_obj:
return Response(data="用户名或密码错误")
else:
token = uuid4() # 创建token
user_obj.user_token = token
user_obj.save()
return Response(data="登录成功",headers={"token":token}) # 返回token到请求头中
url
下面是路由。
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('login/',views.Login.as_view()),
path('api/film/',views.FilmAPI.as_view()),
]
简单尝试
现在我们启动django项目试试。可以发现,当我们在请求头中设置好token并朝api发送GET请求时,它会返回所有的数据。
我们登录的是jack这个用户,他应该只能看到免费电影,而类似泰坦尼克号这种电影是不应该让他看见的。

自定制权限
写一个类,继承BasePermission,重写has_permission()方法,如果权限通过,就返回True,不通过就返回False。
权限校验
接下来我们来写权限校验,has_permission()方法接受两个参数,分别是request和view,也就是视图类的实例化本身。
from rest_framework.permissions import BasePermission
from app01 import models
from django.db.models import Q
class UserPermission(BasePermission):
def has_permission(self, request, view):
if request.auth == 1: # 如果是普通用户,修改当前获取的资源为免费电影
view.queryset = models.Film.objects.filter(film_grade=1)
elif request.auth == 2: # 如果是黄金VIP,则只能获取黄金VIP电影和免费电影
view.queryset = models.Film.objects.filter(Q(film_grade=2) | Q(film_grade=1))
else:
pass # 默认就是获取所有,所以不用修改
return True # 权限校验完成,设置好了。普通用户只能看免费电影
局部使用
下面是局部使用,只需要用一个变量名为permission_classes的列表,将权限校验的类放入即可:
class FilmAPI(ListAPIView,GenericAPIView):
authentication_classes = [app01_auth.LoginAuth] # 必须登录
permission_classes = [app01_permissions.UserPermission] # 做权限设置
queryset = models.Film.objects.all() # 默认查看所有,任何用户都是
serializer_class = serializationClass.FilmModelSerializers
def get(self,request):
return self.list(request)
全局使用
如果是全局使用,则需要到项目全局文件夹下的settings.py中进行设置:
# 全局使用
REST_FRAMEWORK={
'DEFAULT_PERMISSION_CLASSES': [
'app01.app01_permissions.UserPermission',
],
}
如果想取消某个接口的权限认证设置,则在其中设置类属性permission_classes是一个空列表。
如下所示,登录功能不需要验证权限,我们对他取消掉即可。
class Login(APIView):
permission_classes = [] # 取消权限验证设置
def post(self,request):
user_dict = {
"user_name":request.data.get("user_name"),
"user_password":request.data.get("user_password"),
}
user_obj = models.User.objects.filter(**user_dict).first()
if not user_obj:
return Response(data="用户名或密码错误")
else:
token = uuid4() # 创建token
user_obj.user_token = token
user_obj.save()
return Response(data="登录成功",headers={"token":token}) # 返回token到请求头中
结果演示
再次使用jack的token进行登录,可以发现他只会看到免费电影了。

而使用ken的token进行登录,他将看不到钻石VIP的电影,如泰坦尼克号:

倘若使用yunya的token进行登录,则可以查看到所有的电影。

内置权限
如果你是使用auth组件来做的一系列登录等,则可以使用内置权限。
它会判断该用户的is_staff字段是否为True。
内置权限的类使用有很多,如下所示:

基本演示
# 演示一下内置权限的使用:IsAdminUser,控制是否对网站后台有权限的人
# 1 创建超级管理员
# 2 写一个测试视图类
from rest_framework.permissions import IsAdminUser
from rest_framework.authentication import SessionAuthentication
class TestView3(APIView):
authentication_classes=[SessionAuthentication,] # 必须有认证
permission_classes = [IsAdminUser] # 权限设置
def get(self,request,*args,**kwargs):
return Response('这是22222222测试数据,超级管理员可以看')
# 3 超级用户登录到admin,再访问test3就有权限
# 4 正常的话,普通管理员,没有权限看(判断的是is_staff字段)
源码分析
权限校验排在认证校验之后,这在源码中可以查看到。
它的源码相比于认证的源码来说简单的多,认证的执行是在request.user中进行的,而它直接是在当前视图类中进行,所以很简单。
# APIView---->dispatch---->initial--->self.check_permissions(request)(APIView的对象方法)
def check_permissions(self, request):
# 遍历权限对象列表得到一个个权限对象(权限器),进行权限认证 遍历 for (权限认证的实例化对象)
for permission in self.get_permissions():
# 权限类一定有一个has_permission权限方法,用来做权限认证的
# 参数:权限对象self、请求对象request、视图类对象
# 返回值:有权限返回True,无权限返回False
if not permission.has_permission(request, self):
self.permission_denied(
request, message=getattr(permission, 'message', None)
)
drf 权限校验设置与源码分析的更多相关文章
- django身份认证、权限认证、频率校验使用及源码分析
一. 身份认证源码分析 1.1 APIView源码的分析 APIView源码之前分析过https://www.cnblogs.com/maoruqiang/p/11135335.html,里面主要将r ...
- drf复习(一)--原生djangoCBV请求生命周期源码分析、drf自定义配置文件、drf请求生命周期dispatch源码分析
admin后台注册model 一.原生djangoCBV请求生命周期源码分析 原生view的源码路径(django/views/generic/base.py) 1.从urls.py中as_view ...
- ABP源码分析二十二:Navigation
MenuDefinition:封装了导航栏上的主菜单的属性. MenuItemDefinition:封装了主菜单的子菜单的属性.子菜单可以引用其他子菜单构成一个菜单树 UserMenu/UserMen ...
- Log4j2异步情况下怎么防止丢日志的源码分析以及队列等待和拒绝策略分析
org.apache.logging.log4j.core.async.AsyncLoggerConfigDisruptor以下所有源码均在此类中首先我们看下log4j2异步队列的初始化 从这里面我们 ...
- drf 认证校验及源码分析
认证校验 认证校验是十分重要的,如用户如果不登陆就不能访问某些接口. 再比如用户不登陆就不能够对一个接口做哪些操作. drf中认证的写法流程如下: 1.写一个类,继承BaseAuthenticatio ...
- Django(63)drf权限源码分析与自定义权限
前言 上一篇我们分析了认证的源码,一个请求认证通过以后,第二步就是查看权限了,drf默认是允许所有用户访问 权限源码分析 源码入口:APIView.py文件下的initial方法下的check_per ...
- Django之DRF源码分析(二)---数据校验部分
Django之DRF源码分析(二)---数据校验部分 is_valid() 源码 def is_valid(self, raise_exception=False): assert not hasat ...
- drf源码分析系列---权限
权限的使用 全局使用 from rest_framework.permissions import BasePermission from rest_framework import exceptio ...
- DRF cbv源码分析 restful规范10条 drf:APIView的源码 Request的源码 postman的安装和使用
CBV 执行流程 路由配置:url(r'^test/',views.Test.as_view()), --> 根据路由匹配,一旦成功,会执行后面函数(request) --> 本质就是执 ...
随机推荐
- 在Linux系统下搭建和配置一个minio文件服务器(一)
1.minio文件服务器的介绍 Minio 是一个基于Go语言的对象存储服务.它实现了大部分亚马逊S3云存储服务接口,可以看做是是S3的开源版本,非常适合于存储大容量非结构化的数据,例如图片.视频.日 ...
- # mac使用homebrew安装jdk和tomcat
homebrew安装jdk 前提是已经安装homebrew //直接命令行安装 brew cask install homebrew/cask-versions/adoptopenjdk8 homeb ...
- NN相关资源(持续更新)
Iris数据介绍 http://www.cnblogs.com/Belter/p/8831216.html
- p.array 的shape (2,)与(2,1)的分别是什么意思
numpy.ndarray.shap是返回一个数组维度的元组. (2,)与(2,1)的区别如下: ndarray.shape:数组的维度.为一个表示数组在每个维度上大小的整数元组.例如二维数组中, ...
- 【django】本地开发media用户上传文件访问路径找不到
当我们在本地开发的时候,会碰到static可以访问,但是用户上传的文件设置在media下不可访问怎么办?settings配置: 接着在你的urls文件添加: from . import setting ...
- c++ 西安交通大学 mooc 第十三周基础练习&第十三周编程作业
做题记录 风影影,景色明明,淡淡云雾中,小鸟轻灵. c++的文件操作已经好玩起来了,不过掌握好控制结构显得更为重要了. 我这也不做啥题目分析了,直接就题干-代码. 总结--留着自己看 1. 流是指从一 ...
- Windows VS Code 配置 C/C++ 开发环境
准备 Windows [这个相信大家都有 笑: )] VS Code MinGW-w64 C/C++ 安装 MinGw-w64 具体说明细节和安装体验可以在<⑨也懂系列:MinGW-w64安装教 ...
- 2014年 实验二 B2C网上购物
实验二 B2C网上购物 [实验目的] ⑴.熟悉虚拟银行和网上支付的应用 ⑵.熟悉并掌握消费者B2C网上购物和商家的销售处理 [实验条件] ⑴.个人计算机一台 ⑵.计算机通过局域网形式接入互联网 (3) ...
- web中的HTML CSS
HTML 超文本标记语言 页面的结构 首行声明文档类型>根标记>头部标记/主体标记 标记 div 布局 切割 分割 划分区域 spa ...
- ucore操作系统学习笔记(二) ucore lab2物理内存管理分析
一.lab2物理内存管理介绍 操作系统的一个主要职责是管理硬件资源,并向应用程序提供具有良好抽象的接口来使用这些资源. 而内存作为重要的计算机硬件资源,也必然需要被操作系统统一的管理.最初没有操作系统 ...