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时间戳使用和相互转换详解
Dec 11 Python
selenium python浏览器多窗口处理代码示例
Jan 15 Python
Python cookbook(数据结构与算法)对切片命名清除索引的方法
Mar 13 Python
完美解决Python matplotlib绘图时汉字显示不正常的问题
Jan 29 Python
python flask解析json数据不完整的解决方法
May 26 Python
python用win32gui遍历窗口并设置窗口位置的方法
Jul 26 Python
使用python模拟命令行终端的示例
Aug 13 Python
浅析PyTorch中nn.Module的使用
Aug 18 Python
python爬虫 Pyppeteer使用方法解析
Sep 28 Python
python argparse模块通过后台传递参数实例
Apr 20 Python
tensorflow dataset.shuffle、dataset.batch、dataset.repeat顺序区别详解
Jun 03 Python
python 使用elasticsearch 实现翻页的三种方式
Jul 31 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面向对象的方法重载两种版本比较
2008/09/08 PHP
php几个预定义变量$_SERVER用法小结
2014/11/07 PHP
Yii2框架引用bootstrap中日期插件yii2-date-picker的方法
2016/01/09 PHP
javascript笔记 String类replace函数的一些事
2011/09/22 Javascript
jquery无缝向上滚动实现代码
2013/03/29 Javascript
js实现点击注册按钮开始读秒倒计时的小例子
2013/05/11 Javascript
JS 实现点击a标签的时候让其背景更换
2013/10/15 Javascript
使用jQuery实现图片遮罩半透明坠落遮挡
2015/03/16 Javascript
JS实现黑色大气的二级导航菜单效果
2015/09/18 Javascript
javascript实现添加附件功能的方法
2015/11/18 Javascript
基于MVC+EasyUI的web开发框架之使用云打印控件C-Lodop打印页面或套打报关运单信息
2016/08/29 Javascript
浅谈React组件之性能优化
2018/03/02 Javascript
vue通过滚动行为实现从列表到详情,返回列表原位置的方法
2018/08/31 Javascript
Python 的 with 语句详解
2014/06/13 Python
Python中replace方法实例分析
2014/08/20 Python
用Python给文本创立向量空间模型的教程
2015/04/23 Python
深入浅析python定时杀进程
2016/06/06 Python
python线程、进程和协程详解
2016/07/19 Python
Python MySQL 日期时间格式化作为参数的操作
2020/03/02 Python
Pyinstaller打包Scrapy项目的实现步骤
2020/09/22 Python
python实现数学模型(插值、拟合和微分方程)
2020/11/13 Python
详解Python中的文件操作
2021/01/14 Python
用60行代码实现Python自动抢微信红包
2021/02/04 Python
css3实现3D文本悬停改变效果的示例代码
2019/01/16 HTML / CSS
css3实现背景动态渐变效果
2019/12/10 HTML / CSS
汽车专业毕业生自荐信
2013/11/03 职场文书
社团成立邀请函
2014/01/08 职场文书
小孩百日宴答谢词
2014/01/15 职场文书
一年级语文教学反思
2014/02/13 职场文书
三好学生事迹材料
2014/12/24 职场文书
工作自我评价范文
2015/03/05 职场文书
2015年社区妇联工作总结
2015/04/21 职场文书
家庭贫困证明
2015/06/16 职场文书
2016年情人节广告语
2016/01/28 职场文书
Python中的程序流程控制语句
2022/02/24 Python
【海涛教你打dota】体验一超神发条:咱是抢盾专业户
2022/04/01 DOTA