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 + openpyxl处理excel2007文档思路以及心得
Jul 14 Python
Python入门篇之字符串
Oct 17 Python
Python常用随机数与随机字符串方法实例
Apr 09 Python
Python如何获取系统iops示例代码
Sep 06 Python
tensorflow创建变量以及根据名称查找变量
Mar 10 Python
python操作excel文件并输出txt文件的实例
Jul 10 Python
详解pandas中MultiIndex和对象实际索引不一致问题
Jul 23 Python
Python使用gluon/mxnet模块实现的mnist手写数字识别功能完整示例
Dec 18 Python
利用 Python ElementTree 生成 xml的实例
Mar 06 Python
python 生成任意形状的凸包图代码
Apr 16 Python
Python实现石头剪刀布游戏
Jan 20 Python
python glom模块的使用简介
Apr 13 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
比较discuz和ecshop的截取字符串函数php版
2012/09/03 PHP
php获取远程图片体积大小的实例
2013/11/12 PHP
Linux下PHP连接Oracle数据库
2014/08/20 PHP
PHP整合PayPal支付
2015/06/11 PHP
什么是PHP7中的孤儿进程与僵尸进程
2019/04/14 PHP
Laravel 读取 config 下的数据方法
2019/10/13 PHP
Javascript的IE和Firefox兼容性汇编
2006/07/01 Javascript
js form action动态修改方法
2008/11/04 Javascript
flash 得到自身url参数的代码
2009/11/15 Javascript
基于jquery的多彩百分比 动态进度条 投票效果显示效果实现代码
2011/08/28 Javascript
javascript判断ie浏览器6/7版本加载不同样式表的实现代码
2011/12/26 Javascript
seajs1.3.0源码解析之module依赖有序加载
2012/11/07 Javascript
二叉树先序遍历的非递归算法具体实现
2014/01/09 Javascript
jQuery 鼠标经过(hover)事件的延时处理示例
2014/04/14 Javascript
js换图片效果可进行定时操作
2014/06/09 Javascript
详解javascript遍历方式
2015/11/11 Javascript
JS中使用变量保存arguments对象的方法
2016/06/03 Javascript
JavaScript学习笔记整理_关于表达式和语句
2016/09/19 Javascript
jQuery中on方法使用注意事项详解
2017/02/15 Javascript
vue中的计算属性实例详解
2018/09/19 Javascript
jupyter notebook引用from pyecharts.charts import Bar运行报错
2020/04/23 Python
Python selenium抓取微博内容的示例代码
2018/05/17 Python
Django高级编程之自定义Field实现多语言
2019/07/02 Python
详解使用PyInstaller将Pygame库编写的小游戏程序打包为exe文件
2019/08/23 Python
Python大数据之使用lxml库解析html网页文件示例
2019/11/16 Python
如何基于Python + requests实现发送HTTP请求
2020/01/13 Python
python 服务器运行代码报错ModuleNotFoundError的解决办法
2020/09/16 Python
使用Python封装excel操作指南
2021/01/29 Python
Ralph Lauren法国官网:美国高品味时装品牌
2017/12/08 全球购物
Notino意大利:购买香水和化妆品
2018/11/14 全球购物
一套软件开发工程师笔试题
2015/05/18 面试题
恐龙的灭绝教学反思
2014/02/12 职场文书
简单的离婚协议书范本
2014/11/16 职场文书
2015清明节祭奠英烈寄语大全
2015/03/04 职场文书
学校中秋节活动总结
2015/03/23 职场文书
Windows Server 2008配置防火墙策略详解
2022/06/28 Servers