Django-Rest-Framework 权限管理源码浅析(小结)


Posted in Python onNovember 12, 2018

在django的views中不论是用类方式还是用装饰器方式来使用rest框架,django_rest_frame实现权限管理都需要两个东西的配合: authentication_classespermission_classes

# 方式1: 装饰器
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import AllowAny
from rest_framework.response import Response


@api_view(["GET", ])
@permission_classes([AllowAny,])
@authentication_classes([SessionAuthentication, BasicAuthentication])
def test_example(request):
 content = {
   'user': unicode(request.user), # `django.contrib.auth.User` instance.
   'auth': unicode(request.auth), # None
  }
  return Response(content)

# ------------------------------------------------------------
# 方式2: 类
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.views import APIView

class ExampleView(APIView):
 authentication_classes = (SessionAuthentication, BasicAuthentication)
 permission_classes = (AllowAny,)

 def get(self, request, format=None):
  content = {
   'user': unicode(request.user), # `django.contrib.auth.User` instance.
   'auth': unicode(request.auth), # None
  }
  return Response(content)

上面给出的是权限配置的默认方案,写和不写没有区别。 rest框架有自己的settings文件 ,最原始的默认值都可以在里面找到:

Django-Rest-Framework 权限管理源码浅析(小结)

说道rest的settings文件,要覆盖其中的默认行为,特别是权限认证行为,我们只需要在 项目settings文件

中指定你自己的类即可:

REST_FRAMEWORK = {
 ...
 'DEFAULT_AUTHENTICATION_CLASSES': (
  'your_authentication_class_path',
 ),
 ...
}

在rest的settings文件中,获取属性时,会优先加载项目的settings文件中的设置,如果项目中没有的,才加载自己的默认设置:

初始化api_settings对象

api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)

APISettings 类中获取属性时优先获取项目的settings文件中 REST_FRAMEWORK 对象的值,没有的再找自己的默认值

@property
def user_settings(self):
 if not hasattr(self, '_user_settings'):
  # _user_settings默认为加载项目settings文件中的REST_FRAMEWORK对象
  self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})
 return self._user_settings

def __getattr__(self, attr):
 if attr not in self.defaults:
  raise AttributeError("Invalid API setting: '%s'" % attr)

 try:
  # Check if present in user settings
  # 优先加载user_settings,即项目的settings文件,没有就用默认
  val = self.user_settings[attr]
 except KeyError:
  # Fall back to defaults
  val = self.defaults[attr]

 # Coerce import strings into classes
 if attr in self.import_strings:
  val = perform_import(val, attr)

 # Cache the result
 self._cached_attrs.add(attr)
 setattr(self, attr, val)
 return val

在rest中settings中,能自动检测 项目settings 的改变,并重新加载自己的配置文件:

Django-Rest-Framework 权限管理源码浅析(小结)

权限管理原理浅析

rest框架是如何使用 authentication_classespermission_classes ,并将二者配合起来进行权限管理的呢?

使用类方式实现的时候,我们都会直接或间接的使用到rest框架中的APIVIEW,在 urls.py 中使用该类的 as_view 方法来构建router

# views.py
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated


class ExampleAPIView(APIView):
 permission_classes = (IsAuthenticated,)
 ...
 
# -----------------------------
from django.conf.urls import url, include

from .views import ExampleAPIView

urlpatterns = [
 url(r'^example/(?P<example_id>[-\w]+)/examples/?$',
  ExampleAPIView.as_view()),
]

在我们调用 APIVIEW.as_view() 的时候,该类会调用父类的同名方法:

Django-Rest-Framework 权限管理源码浅析(小结)

父类的同名方法中,调用了dispatch方法:

Django-Rest-Framework 权限管理源码浅析(小结)

rest 重写 了该方法,在该方法中对requset做了一次服务端初始化(加入验证信息等)处理

Django-Rest-Framework 权限管理源码浅析(小结)

调用权限管理

Django-Rest-Framework 权限管理源码浅析(小结)

在权限管理中会使用默认的或是你指定的权限认证进行验证: 这里只是做验证并存储验证结果 ,这里操作完后authentication_classes的作用就完成了。验证结果会在后面指定的 permission_classes 中使用!

def get_authenticators(self):
  """
  Instantiates and returns the list of authenticators that this view can use.
  """
  return [auth() for auth in self.authentication_classes]

通过指定的permission_classes确定是否有当前接口的访问权限:

class IsAuthenticatedOrReadOnly(BasePermission):
 """
 The request is authenticated as a user, or is a read-only request.
 """

 def has_permission(self, request, view):
  return (
   request.method in SAFE_METHODS or
   request.user and
   request.user.is_authenticated
  )

最后,不管有没有使用permission_classes来决定是否能访问,默认的或是你自己指定的authentication_classes都会执行并将权限结果放在request中!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
让python的Cookie.py模块支持冒号做key的方法
Dec 28 Python
Python编程中的for循环语句学习教程
Oct 14 Python
简单解决Python文件中文编码问题
Nov 22 Python
tensorflow TFRecords文件的生成和读取的方法
Feb 06 Python
Python设计模式之组合模式原理与用法实例分析
Jan 11 Python
Flask 上传自定义头像的实例详解
Jan 09 Python
解决pycharm不能自动补全第三方库的函数和属性问题
Mar 12 Python
详解Django中views数据查询使用locals()函数进行优化
Aug 24 Python
详解Django中 render() 函数的使用方法
Apr 22 Python
MATLAB 全景图切割及盒图显示的实现步骤
May 14 Python
Python实现查询剪贴板自动匹配信息的思路详解
Jul 09 Python
python获取带有返回值的多线程
May 02 Python
使用python将时间转换为指定的格式方法
Nov 12 #Python
pandas 快速处理 date_time 日期格式方法
Nov 12 #Python
python内置数据类型之列表操作
Nov 12 #Python
python pandas读取csv后,获取列标签的方法
Nov 12 #Python
对pandas的行列名更改与数据选择详解
Nov 12 #Python
Python numpy.array()生成相同元素数组的示例
Nov 12 #Python
浅谈numpy生成数组的零值问题
Nov 12 #Python
You might like
浅析THINKPHP的addAll支持的最大数据量
2015/02/03 PHP
Yii2中事务的使用实例代码详解
2016/09/07 PHP
PHP获取星期几的常用方法小结
2018/12/18 PHP
php+js实现的无刷新下载文件功能示例
2019/08/23 PHP
jQuery选择头像并实时显示的代码
2010/06/27 Javascript
JS删除数组元素的函数介绍
2013/03/27 Javascript
js Array对象的扩展函数代码
2013/04/24 Javascript
屏蔽IE弹出&quot;您查看的网页正在试图关闭窗口,是否关闭此窗口&quot;的方法
2013/12/31 Javascript
JQuery以JSON方式提交数据到服务端示例代码
2014/05/05 Javascript
js怎么判断flash swf文件是否加载完毕
2014/08/14 Javascript
javaScript中with函数用法实例分析
2015/06/08 Javascript
JavaScript中的setUTCDate()方法使用详解
2015/06/11 Javascript
jQuery 3.0十大新特性
2016/07/06 Javascript
JavaScript实现通过select标签跳转网页的方法
2016/09/29 Javascript
JavaScript关联数组用法分析【概念、定义、遍历】
2017/03/15 Javascript
HTML中使背景图片自适应浏览器大小实例详解
2017/04/06 Javascript
基于node.js之调试器详解
2017/08/22 Javascript
vue.js实现的绑定class操作示例
2018/07/06 Javascript
JS使用Prim算法和Kruskal算法实现最小生成树
2019/01/17 Javascript
vue-cli webpack配置文件分析
2019/05/20 Javascript
Python八大常见排序算法定义、实现及时间消耗效率分析
2018/04/27 Python
有关Python的22个编程技巧
2018/08/29 Python
Python 使用Numpy对矩阵进行转置的方法
2019/01/28 Python
Window系统下Python如何安装OpenCV库
2020/03/05 Python
Python SMTP配置参数并发送邮件
2020/06/16 Python
Python爬虫爬取有道实现翻译功能
2020/11/27 Python
飞利浦比利时官方网站:Philips比利时
2016/08/24 全球购物
Smashbox英国官网:美国知名彩妆品牌
2017/11/13 全球购物
关于圣诞节的广播稿
2014/01/26 职场文书
《童年的发现》教学反思
2014/02/14 职场文书
酒店开业庆典主持词
2014/03/21 职场文书
教师节老师寄语
2015/05/28 职场文书
浅谈Python类的单继承相关知识
2021/05/12 Python
 Python 中 logging 模块使用详情
2022/03/03 Python
python 闭包函数详细介绍
2022/04/19 Python
python开发人人对战的五子棋小游戏
2022/05/02 Python