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实现在线程里运行scrapy的方法
Apr 07 Python
python编写分类决策树的代码
Dec 21 Python
Python Requests模拟登录实现图书馆座位自动预约
Apr 27 Python
python+opencv实现高斯平滑滤波
Jul 21 Python
Python数据类型之Dict字典实例详解
May 07 Python
对Python中小整数对象池和大整数对象池的使用详解
Jul 09 Python
python字符串反转的四种方法详解
Dec 02 Python
Python3的unicode编码转换成中文的问题及解决方案
Dec 10 Python
python实现IOU计算案例
Apr 12 Python
Python 操作 PostgreSQL 数据库示例【连接、增删改查等】
Apr 21 Python
python读取yaml文件后修改写入本地实例
Apr 27 Python
一文带你了解Python 四种常见基础爬虫方法介绍
Dec 04 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表单习惯用的正则表达式
2017/10/11 PHP
ThinkPHP类似AOP思想的参数验证的实现方法
2019/12/18 PHP
html向js方法传递参数具体实现
2013/08/08 Javascript
使用javascript实现ListBox左右全选,单选,多选,全请
2013/11/07 Javascript
父页面显示遮罩层弹出半透明状态的dialog
2014/03/04 Javascript
jquery插件开发之实现google+圈子选择功能
2014/03/10 Javascript
js用闭包遍历树状数组的方法
2014/03/19 Javascript
JavaScript实现twitter puddles算法实例
2014/12/06 Javascript
借助FileReader实现将文件编码为Base64后通过AJAX上传
2015/12/24 Javascript
jQuery获取复选框被选中数量及判断选择值的方法详解
2016/05/25 Javascript
大型JavaScript应用程序架构设计模式
2016/06/29 Javascript
网络传输协议(http协议)
2016/11/18 Javascript
基于vue.js轮播组件vue-awesome-swiper实现轮播图
2017/03/17 Javascript
node内置调试方法总结
2018/02/22 Javascript
web页面和微信小程序页面实现瀑布流效果
2018/09/26 Javascript
vue-cli3 DllPlugin 提取公用库的方法
2019/04/24 Javascript
三步搞定:Vue.js调用Android原生操作
2020/09/07 Javascript
python实现解数独程序代码
2017/04/12 Python
wxPython的安装图文教程(Windows)
2017/12/28 Python
python实现括号匹配的思路详解
2018/08/23 Python
python 高效去重复 支持GB级别大文件的示例代码
2018/11/08 Python
python 2.7 检测一个网页是否能正常访问的方法
2018/12/26 Python
Python实现去除图片中指定颜色的像素功能示例
2019/04/13 Python
如何通过Python实现标签云算法
2019/07/02 Python
Python调用百度根据经纬度查询地址的示例代码
2019/07/07 Python
Python 200行代码实现一个滑动验证码过程详解
2019/07/11 Python
利用python实现后端写网页(flask框架)
2021/02/28 Python
小区消防演习方案
2014/02/21 职场文书
主题教育活动总结
2014/05/05 职场文书
品牌推广活动策划方案
2014/08/19 职场文书
推广活动策划方案
2014/08/23 职场文书
职业道德模范事迹材料
2014/08/24 职场文书
工作表扬信范文
2015/01/17 职场文书
大学生旷课检讨书1000字
2015/02/19 职场文书
年终奖金发放管理制度,中小企业适用,拿去救急吧!
2019/07/12 职场文书
详解Mysql数据库平滑扩容解决高并发和大数据量问题
2022/05/25 MySQL