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程序与系统shell交互的方式
Apr 09 Python
Python的Scrapy爬虫框架简单学习笔记
Jan 20 Python
2018年Python值得关注的开源库、工具和开发者(总结篇)
Jan 04 Python
python OpenCV学习笔记之绘制直方图的方法
Feb 08 Python
python删除服务器文件代码示例
Feb 09 Python
Tensorflow卷积神经网络实例
May 24 Python
python实现文本进度条 程序进度条 加载进度条 单行刷新功能
Jul 03 Python
Django 迁移、操作数据库的方法
Aug 02 Python
python实现ip地址的包含关系判断
Feb 07 Python
Python requests.post方法中data与json参数区别详解
Apr 30 Python
django正续或者倒序查库实例
May 19 Python
Pycharm配置lua编译环境过程图解
Nov 28 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
javascript+php实现根据用户时区显示当地时间的方法
2015/03/11 PHP
php实现的mongodb操作类实例
2015/04/03 PHP
PHP+shell实现多线程的方法
2015/07/01 PHP
PHP使用pear自带的mail类库发邮件的方法
2015/07/08 PHP
php微信公众号开发之简答题
2018/10/20 PHP
用JQuery 实现的自定义对话框
2007/03/24 Javascript
javascript来定义类的规范小结
2010/11/19 Javascript
bootstrap侧边栏圆点导航
2017/01/11 Javascript
jQuery选取所有复选框被选中的值并用Ajax异步提交数据的实例
2017/08/04 jQuery
JavaScript实现body内任意节点的自定义属性功能示例
2017/09/18 Javascript
Vue源码解析之数据响应系统的使用
2019/04/24 Javascript
怎么使用javascript深度拷贝一个数组
2019/06/06 Javascript
微信小程序8种数据通信的方式小结
2020/02/03 Javascript
element-ui table行点击获取行索引(index)并利用索引更换行顺序
2020/02/27 Javascript
vue-openlayers实现地图坐标弹框效果
2020/09/24 Javascript
[48:39]Ti4主赛事胜者组第一天 EG vs NEWBEE 2
2014/07/19 DOTA
Python可变参数函数用法实例
2015/07/07 Python
在pandas中一次性删除dataframe的多个列方法
2018/04/10 Python
Python3.5集合及其常见运算实例详解
2019/05/01 Python
PyQt5实现从主窗口打开子窗口的方法
2019/06/19 Python
python 列表转为字典的两个小方法(小结)
2019/06/28 Python
Python序列类型的打包和解包实例
2019/12/21 Python
基于python检查SSL证书到期情况代码实例
2020/04/04 Python
python3 中使用urllib问题以及urllib详解
2020/08/03 Python
美国购买汽车零件网站:Buy Auto Parts
2018/04/02 全球购物
与世界上最好的跑步专业品牌合作:Fleet Feet
2019/03/22 全球购物
英文自荐信
2013/12/15 职场文书
中国梦演讲稿教师篇
2014/04/23 职场文书
品酒会策划方案
2014/05/26 职场文书
党员个人批评与自我批评
2014/10/14 职场文书
公司庆典欢迎词
2015/01/26 职场文书
小学教师教育随笔
2015/08/14 职场文书
交通安全教育心得体会
2016/01/15 职场文书
2019年学校消防安全责任书(2篇)
2019/10/09 职场文书
一文帮你理解PReact10.5.13源码
2021/04/03 Javascript
在Python 中将类对象序列化为JSON
2022/04/06 Python