权限校验

   权限校验和认证校验必须同时使用,并且权限校验是排在认证校验之后的,这在源码中可以查找到其执行顺序。

   权限校验也很重要,认证校验可以确保一个用户登录之后才能对接口做操作,而权限校验可以依据这个登录用户的类型来限定能对接口做那些操作。

准备工作

模型表

   下面是模型表,对于不同等级的用户,访问同一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()方法接受两个参数,分别是requestview,也就是视图类的实例化本身。

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到请求头中

结果演示

   再次使用jacktoken进行登录,可以发现他只会看到免费电影了。

  

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

  

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

  

内置权限

   如果你是使用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 权限校验设置与源码分析的更多相关文章

  1. django身份认证、权限认证、频率校验使用及源码分析

    一. 身份认证源码分析 1.1 APIView源码的分析 APIView源码之前分析过https://www.cnblogs.com/maoruqiang/p/11135335.html,里面主要将r ...

  2. drf复习(一)--原生djangoCBV请求生命周期源码分析、drf自定义配置文件、drf请求生命周期dispatch源码分析

    admin后台注册model  一.原生djangoCBV请求生命周期源码分析 原生view的源码路径(django/views/generic/base.py) 1.从urls.py中as_view ...

  3. ABP源码分析二十二:Navigation

    MenuDefinition:封装了导航栏上的主菜单的属性. MenuItemDefinition:封装了主菜单的子菜单的属性.子菜单可以引用其他子菜单构成一个菜单树 UserMenu/UserMen ...

  4. Log4j2异步情况下怎么防止丢日志的源码分析以及队列等待和拒绝策略分析

    org.apache.logging.log4j.core.async.AsyncLoggerConfigDisruptor以下所有源码均在此类中首先我们看下log4j2异步队列的初始化 从这里面我们 ...

  5. drf 认证校验及源码分析

    认证校验 认证校验是十分重要的,如用户如果不登陆就不能访问某些接口. 再比如用户不登陆就不能够对一个接口做哪些操作. drf中认证的写法流程如下: 1.写一个类,继承BaseAuthenticatio ...

  6. Django(63)drf权限源码分析与自定义权限

    前言 上一篇我们分析了认证的源码,一个请求认证通过以后,第二步就是查看权限了,drf默认是允许所有用户访问 权限源码分析 源码入口:APIView.py文件下的initial方法下的check_per ...

  7. Django之DRF源码分析(二)---数据校验部分

    Django之DRF源码分析(二)---数据校验部分 is_valid() 源码 def is_valid(self, raise_exception=False): assert not hasat ...

  8. drf源码分析系列---权限

    权限的使用 全局使用 from rest_framework.permissions import BasePermission from rest_framework import exceptio ...

  9. DRF cbv源码分析 restful规范10条 drf:APIView的源码 Request的源码 postman的安装和使用

    CBV 执行流程 路由配置:url(r'^test/',views.Test.as_view()),  --> 根据路由匹配,一旦成功,会执行后面函数(request) --> 本质就是执 ...

随机推荐

  1. uni-app支付功能

    扫码查看原文 前言 近期一直在使用APP开发多端应用,IOS的APP.安卓的APP和H5网页,其中开发的APP使用到了微信和支付宝的支付,在此给大家分享出来,一起使用 前置条件: 开发环境:windo ...

  2. Centos-跟踪数据传输路由状态-traceroute

    traceroute 显示网卡数据包传输到指定主机的路径信息,追踪数据传输路由状况,默认数据包大小38字节 相关选项 -i   使用指定网络接口发送数据 -n 使用IP而不使用主机名 -v 显示命令的 ...

  3. Go-The process cannot access the file because it is being used by another process.

    where? Go程序在读取文件时候 why? 因为有其他进程也在读取和Go程序想要读取的文件,参数冲突 way? 关闭其他程序进程对该文件的读取操作

  4. 卧槽!最新编程语言排名,Java 沦为老二。。

    2020 年 9 月刚过去,栈长看了下最新的 tiobe 编程语言榜,牛逼啊,C 语言居然登顶了,Java 下降 3 个点,沦为老二的位置. 数据来源TIOBE: https://www.tiobe. ...

  5. Python self用法详解

    在定义类的过程中,无论是显式创建类的构造方法,还是向类中添加实例方法,都要求将 self 参数作为方法的第一个参数.例如,定义一个 Person 类: class Person: def __init ...

  6. VS 高级版本新建的项目如何降级使低版本 VS 可以打开

    转载:https://blog.csdn.net/u012814856/article/details/70325267 一.引言 这里因为工作的原因,公司项目使用的是 VS2015 的编译环境,但是 ...

  7. 【题解】SP1812 【LCS2 - Longest Common Substring II 】

    \(\text{Suffix Tree:}\)我来啦我来啦 \(\text{Solution:}\) 题目要求求好几个串串的\(\text{LCS.}\) 由于串串的数量并不多,所以我们把它们塞到一个 ...

  8. vue 异步提交php 两种方式传值

    1.首先要在php的入口文件写上一条代码,允许异步提交 header("ACCESS-CONTROL-ALLOW-ORIGIN:*"); 2.在vue有两种方式将数据异步提交到ph ...

  9. dockerfile-maven-plugin极简教程

    目录 一.简介 二.概述 三.将spring-boot-app打包成docker镜像 创建示例应用 修改pom文件 增加Dockerfile文件 使用Maven打包应用 运行应用镜像 四.分析mvn ...

  10. 《流畅的Python》第三部分 把函数视作对象 【一等函数】【使用一等函数实现设计模式】【函数装饰器和闭包】

    第三部分 第5章 一等函数 一等对象 在运行时创建 能赋值给变量或数据结构中的元素 能作为参数传递给函数 能作为函数的返回结果 在Python中,所有函数都是一等对象 函数是对象 函数本身是 func ...