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 urlopen()函数 示例分享
Jun 12 Python
python搜索指定目录的方法
Apr 29 Python
自己编程中遇到的Python错误和解决方法汇总整理
Jun 03 Python
Python cookbook(数据结构与算法)根据字段将记录分组操作示例
Mar 19 Python
python利用小波分析进行特征提取的实例
Jan 09 Python
python Tkinter版学生管理系统
Feb 20 Python
10行Python代码计算汽车数量的实现方法
Oct 23 Python
python3中rank函数的用法
Nov 27 Python
利用Python裁切tiff图像且读取tiff,shp文件的实例
Mar 10 Python
浅谈django channels 路由误导
May 28 Python
Python 如何反方向迭代一个序列
Jul 28 Python
python ansible自动化运维工具执行流程
Jun 24 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 Web开发MVC框架的Smarty使用说明
2013/04/19 PHP
php抽奖小程序的实现代码
2013/06/18 PHP
php中stdClass的用法分析
2015/02/27 PHP
Twig模板引擎用法入门教程
2016/01/20 PHP
PHP实现RTX发送消息提醒的实例代码
2017/01/03 PHP
PHP实现图片批量打包下载功能
2017/03/01 PHP
Paypal实现循环扣款(订阅)功能
2017/03/23 PHP
php之可变变量的实例详解
2017/09/12 PHP
Javascript attachEvent传递参数的办法
2009/12/14 Javascript
使用js获取地址栏中传递的值
2013/07/02 Javascript
解析jQuery与其它js(Prototype)库兼容共存
2013/07/04 Javascript
javascript中的parseInt和parseFloat区别
2013/07/12 Javascript
SuperSlide2实现图片滚动特效
2014/06/20 Javascript
jquery easyui使用心得
2014/07/07 Javascript
详解原生JavaScript实现jQuery中AJAX处理的方法
2016/05/10 Javascript
js实现的页面加载完毕之前loading提示效果完整示例【附demo源码下载】
2016/08/02 Javascript
js中遍历Map对象的简单实例
2016/08/08 Javascript
在js中做数字字符串补0(js补零)
2017/03/25 Javascript
实现div内部滚动条滚动到底部和顶部的代码
2017/11/15 Javascript
基于JavaScript的数据结构队列动画实现示例解析
2020/08/06 Javascript
手动实现把python项目发布为exe可执行程序过程分享
2014/10/23 Python
编写Python脚本来获取mp3文件tag信息的教程
2015/05/04 Python
Python中使用装饰器时需要注意的一些问题
2015/05/11 Python
整理Python中的赋值运算符
2015/05/13 Python
Python读取YAML文件过程详解
2019/12/30 Python
Windows下pycharm安装第三方库失败(通用解决方案)
2020/09/17 Python
英国时尚饰品和发饰购物网站:Claire’s
2017/07/04 全球购物
全球领先的全景影像品牌:Insta360
2019/08/21 全球购物
监察局领导班子四风问题整改措施思想汇报
2014/10/05 职场文书
2014年环保工作总结
2014/11/26 职场文书
股东大会通知
2015/04/24 职场文书
员工离职通知函
2015/04/25 职场文书
初中信息技术教学反思
2016/02/16 职场文书
MIME类型中application/xml与text/xml的区别介绍
2022/01/18 HTML / CSS
springboot新建项目pom.xml文件第一行报错的解决
2022/01/18 Java/Android
微信小程序APP的生命周期及页面的生命周期
2022/04/19 Javascript