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爬虫爬取网页表格数据
Mar 07 Python
详谈Python3 操作系统与路径 模块(os / os.path / pathlib)
Apr 26 Python
python线程池threadpool使用篇
Apr 27 Python
十分钟利用Python制作属于你自己的个性logo
May 07 Python
对pycharm代码整体左移和右移缩进快捷键的介绍
Jul 16 Python
Python读取stdin方法实例
May 24 Python
Python之——生成动态路由轨迹图的实例
Nov 22 Python
Python常用库大全及简要说明
Jan 17 Python
python小程序之4名牌手洗牌发牌问题解析
May 15 Python
浅谈tensorflow使用张量时的一些注意点tf.concat,tf.reshape,tf.stack
Jun 23 Python
python使用smtplib模块发送邮件
Dec 17 Python
如何用python开发Zeroc Ice应用
Jan 29 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下编码转换函数mb_convert_encoding与iconv的使用说明
2009/12/16 PHP
PHP substr 截取字符串出现乱码问题解决方法[utf8与gb2312]
2011/12/16 PHP
php长字符串定义方法
2012/07/12 PHP
php daddslashes()和 saddslashes()有哪些区别分析
2012/10/26 PHP
php简单实现查询数据库返回json数据
2015/04/16 PHP
php实现在新浪云中使用imagick生成缩略图并上传的方法
2016/09/26 PHP
laravel异步监控定时调度器实例详解
2019/06/21 PHP
Auntion-TableSort国人写的一个javascript表格排序的东西
2007/11/12 Javascript
jQuery第三课 修改元素属性及内容的代码
2010/03/14 Javascript
JS实现固定在右下角可展开收缩DIV层的方法
2015/02/13 Javascript
深入浅析JavaScript系列(13):This? Yes,this!
2016/01/05 Javascript
jQuery如何跳转到另一个网页 就这么简单
2016/12/28 Javascript
JS控制鼠标拒绝点击某一按钮的实例
2017/12/29 Javascript
vue父组件向子组件(props)传递数据的方法
2018/01/02 Javascript
layui中table表头样式修改方法
2018/08/15 Javascript
从零开始在NPM上发布一个Vue组件的方法步骤
2018/12/20 Javascript
[44:39]2014 DOTA2国际邀请赛中国区预选赛 NE VS CNB
2014/05/21 DOTA
Python的lambda匿名函数的简单介绍
2013/04/25 Python
在Python中使用lambda高效操作列表的教程
2015/04/24 Python
Python编写生成验证码的脚本的教程
2015/05/04 Python
Python3写入文件常用方法实例分析
2015/05/22 Python
Python实现单词翻译功能
2017/06/06 Python
python3 shelve模块的详解
2017/07/08 Python
python3实现磁盘空间监控
2018/06/21 Python
Python3中_(下划线)和__(双下划线)的用途和区别
2019/04/26 Python
分享8点超级有用的Python编程建议(推荐)
2019/10/13 Python
使用matplotlib绘制图例标签中带有公式的图
2019/12/13 Python
解决Python使用列表副本的问题
2019/12/19 Python
python基于三阶贝塞尔曲线的数据平滑算法
2019/12/27 Python
Python批量将图片灰度化的实现代码
2020/04/11 Python
Python如何实现爬取B站视频
2020/05/20 Python
Spring http服务远程调用实现过程解析
2020/06/11 Python
记一次django内存异常排查及解决方法
2020/08/07 Python
省级青年文明号申报材料
2014/05/23 职场文书
详细的本科生职业生涯规划范文
2014/09/16 职场文书
医生辞职信范文
2015/03/02 职场文书