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 14 Python
一些Python中的二维数组的操作方法
May 02 Python
实例说明Python中比较运算符的使用
May 13 Python
在Python的Django框架下使用django-tagging的教程
May 30 Python
Python使用pip安装pySerial串口通讯模块
Apr 20 Python
Python 正则表达式匹配字符串中的http链接方法
Dec 25 Python
利用matplotlib实现根据实时数据动态更新图形
Dec 13 Python
基于python实现上传文件到OSS代码实例
May 09 Python
Python如何实现邮件功能
May 27 Python
Python json解析库jsonpath原理及使用示例
Nov 25 Python
Django自带的用户验证系统实现
Dec 18 Python
Python爬虫入门案例之爬取二手房源数据
Oct 16 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输出xml必须header的解决方法
2014/10/17 PHP
详解HTTP Cookie状态管理机制
2016/01/14 PHP
PHP水印类,支持添加图片、文字、填充颜色区域的实现
2017/02/04 PHP
js 获取、清空input type=&quot;file&quot;的值(示例代码)
2013/12/24 Javascript
js登录弹出层特效
2014/03/07 Javascript
node.js开机自启动脚本文件
2014/12/24 Javascript
jQuery搜索同辈元素方法
2015/02/10 Javascript
HTML5 JS压缩图片并获取图片BASE64编码上传
2020/11/16 Javascript
Vue自定义指令介绍(2)
2016/12/08 Javascript
Ajax 加载数据 练习代码
2017/01/05 Javascript
Javascript别踩白块儿(钢琴块儿)小游戏实现代码
2017/07/20 Javascript
浅谈webpack打包过程中因为图片的路径导致的问题
2018/02/21 Javascript
angularJs-$http实现百度搜索时的动态下拉框示例
2018/02/27 Javascript
简单说说angular.json文件的使用
2018/10/29 Javascript
webpack打包多页面的方法
2018/11/30 Javascript
js实现简单分页导航栏效果
2019/06/28 Javascript
JavaScript字符串处理常见操作方法小结
2019/11/15 Javascript
浅析vue-router实现原理及两种模式
2020/02/11 Javascript
vue3.0 加载json的方法(非ajax)
2020/10/26 Javascript
js实现鼠标切换图片(无定时器)
2021/01/27 Javascript
详解js创建对象的几种方式和对象方法
2021/03/01 Javascript
Python实现把数字转换成中文
2015/06/29 Python
python3利用tcp实现文件夹远程传输
2018/07/28 Python
搭建python django虚拟环境完整步骤详解
2019/07/08 Python
python 使用socket传输图片视频等文件的实现方式
2019/08/07 Python
Django Docker容器化部署之Django-Docker本地部署
2019/10/09 Python
python 生成器和迭代器的原理解析
2019/10/12 Python
基于python图书馆管理系统设计实例详解
2020/08/05 Python
阿迪达斯意大利在线商店:adidas意大利
2016/09/19 全球购物
Mountain Warehouse波兰官方网站:英国户外品牌
2019/08/29 全球购物
如何进行Linux分区优化
2013/02/12 面试题
教师学习群众路线心得体会
2014/11/04 职场文书
万能检讨书
2015/01/27 职场文书
酒店仓管员岗位职责
2015/04/01 职场文书
欠款起诉书范文
2015/05/19 职场文书
openstack中的rpc远程调用的方法
2021/07/09 Python