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连接MySQL、MongoDB、Redis、memcache等数据库的方法
Nov 15 Python
在Python的Flask框架中构建Web表单的教程
Jun 04 Python
Python实现的选择排序算法示例
Nov 29 Python
python根据unicode判断语言类型实例代码
Jan 17 Python
详谈python3 numpy-loadtxt的编码问题
Apr 29 Python
python 随机生成10位数密码的实现代码
Jun 27 Python
python写入数据到csv或xlsx文件的3种方法
Aug 23 Python
解决pycharm上的jupyter notebook端口被占用问题
Dec 17 Python
Python中断多重循环的几种方式详解
Feb 10 Python
python中怎么表示空值
Jun 19 Python
python程序需要编译吗
Jun 19 Python
Python 避免字典和元组的多重嵌套问题
Jul 15 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
PHP 设置MySQL连接字符集的方法
2011/01/02 PHP
PHP APC缓存配置、使用详解
2014/03/06 PHP
递归删除一个节点以及该节点下的所有节点示例
2014/03/19 PHP
PHP常用操作类之通信数据封装类的实现
2017/07/16 PHP
JavaScript常用全局属性与方法记录积累
2013/07/03 Javascript
JavaScript制作的可折叠弹出式菜单示例
2014/04/04 Javascript
使用原生js写的一个简单slider
2014/04/29 Javascript
js使用onmousemove和onmouseout获取鼠标坐标的方法
2015/03/31 Javascript
学习JavaScript设计模式(封装)
2015/11/26 Javascript
jQuery文件上传控件 Uploadify 详解
2016/06/20 Javascript
AngularJS操作键值对象类似java的hashmap(填坑小结)
2016/11/12 Javascript
Angular.JS判断复选框checkbox是否选中并实时显示
2016/11/30 Javascript
js判断iframe中元素是否存在的实现代码
2016/12/24 Javascript
jQuery时间验证和转换为标准格式的时间格式
2017/03/06 Javascript
Angular多选、全选、批量选择操作实例代码
2017/03/10 Javascript
微信JSAPI Ticket接口签名详解
2020/06/28 Javascript
浅谈Vue Element中Select下拉框选取值的问题
2018/03/01 Javascript
深入理解js 中async 函数的含义和用法
2018/05/13 Javascript
最适应的vue.js的form提交涉及多种插件【推荐】
2018/08/27 Javascript
vue 本地服务不能被外部IP访问的完美解决方法
2018/10/29 Javascript
详解微信小程序调用支付接口支付
2019/04/28 Javascript
JavaScript使用面向对象实现的拖拽功能详解
2019/06/12 Javascript
微信小程序框架的页面布局代码
2019/08/17 Javascript
基于leaflet.js实现修改地图主题样式的流程分析
2020/05/15 Javascript
python 运算符 供重载参考
2009/06/11 Python
python binascii 进制转换实例
2019/06/12 Python
Python自动化办公Excel模块openpyxl原理及用法解析
2020/11/05 Python
html5 Web SQL Database 之事务处理函数transaction与executeSQL解析
2013/11/07 HTML / CSS
html5 canvas简单封装一个echarts实现不了的饼图
2018/06/12 HTML / CSS
皇家阿尔伯特英国官方商店:Royal Albert骨瓷
2019/03/25 全球购物
初中校园之声广播稿
2014/01/15 职场文书
幼儿园教师教学反思
2014/02/06 职场文书
同学聚会策划方案
2014/06/06 职场文书
对外汉语专业大学生职业生涯规划书
2014/10/11 职场文书
2014年小学图书室工作总结
2014/12/09 职场文书
小学英语教师研修感悟
2015/11/18 职场文书