一、权限示例

需求:不同的用户类型有不同的权限

  • 普通用户:只能查看个人信息相关,序号:1
  • VIP 用户:只能查看个人信息相关,序号:2
  • SVIP 用户:查看订单相关信息,序号:3

1、新建 app/utils/permission.py

class SVIPPermission(object):
def has_permission(self, request, view):
"""是否有权限"""
if request.user.user_type != 3:
return False
return True class MyPermission(object):
"""普通、VIP 用户"""
def has_permission(self, request, view):
"""是否有权限"""
if request.user.user_type == 3:
return False
return True

如果用户类型为 3 即 SVIP,那么就返回 True,否则返回 False。

Note:只有登录后的用户才有 request.user,即在用户认证的时候,返回用户对象

2、views.py

from django.shortcuts import render, HttpResponse
from rest_framework.views import APIView
from rest_framework.authentication import BasicAuthentication
import hashlib
import time
from app import models
from django.http import JsonResponse
from .utils.auth import MyAuthentication
from .utils.permission import SVIPPermission class OrderView(APIView):
"""订单管理"""
# authentication_classes = [MyAuthentication, ] # 添加认证(因为已经全局设置了认证,所有就不单独设置了) permission_classes = [SVIPPermission, ] # 权限 def get(self, request, *args, **kwargs):
ret = {'code': 1000, 'msg': None, 'data': None, }
ret['data'] = ORDER_DICT
print(request.user)
return JsonResponse(ret) class UserInfo(APIView):
"""用户个人信息"""
permission_classes = [MyPermission, ] def get(self, request, *args, **kwargs):
user_name = request.user.username
return HttpResponse(user_name)

3、现在带上 token(表示已经登录),查看订单:

SVIP 用户:

4、查看用户个人信息:(rose:普通用户)

5、project/urls.py

为了遵循 RESTful API 规范,现在将 URL 修改为如下:

from django.contrib import admin
from django.urls import path
from app.views import IndexView, OrderView, UserInfo urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/index/', IndexView.as_view()),
path('api/v1/order/', OrderView.as_view()),
path('api/v1/info/', UserInfo.as_view()) ]

二、全局配置

与认证一样,权限也可以全局配置和局部配置,全局配置可以使得所有的视图类生效,需要在 settings 中配置:

REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ['app.utils.auth.MyAuthentication', ],
"UNAUTHENTICATED_USER": lambda: '匿名用户',
"UNAUTHENTICATED_TOKEN": None,
"DEFAULT_PERMISSION_CLASSES": ['app.utils.permission.SVIPPermission'], # 这句 }

如果想配置没有访问权限返回的信息,可以修改 app/utils/permission.py

class SVIPPermission(object):
message = '必须 SVIP 才能访问!' # 这句
def has_permission(self, request, view):
"""是否有权限"""
if request.user.user_type != 3:
return False
return True

三、内置权限

rest framework 也有内置的权限 rest_framework/permissions.py

@six.add_metaclass(BasePermissionMetaclass)
class BasePermission(object):
"""
A base class from which all permission classes should inherit.
""" def has_permission(self, request, view):
"""
Return `True` if permission is granted, `False` otherwise.
"""
return True def has_object_permission(self, request, view, obj):
"""
Return `True` if permission is granted, `False` otherwise.
"""
return True

自定义的权限类,最好要继承 BasePermission

# app/utils/permisiion.py
from rest_framework.permissions import BasePermission class SVIPPermission(BasePermission):
message = '必须 SVIP 才能访问!'
def has_permission(self, request, view):
"""是否有权限"""
if request.user.user_type != 3:
return False
return True

四、权限认证流程(源码)

1、请求过来先执行 dispatch() 方法,dispatch() 方法中 initial() 初始化请求相关信息:

def initial(self, request, *args, **kwargs):
"""
Runs anything that needs to occur prior to calling the method handler.
"""
self.format_kwarg = self.get_format_suffix(**kwargs) # Perform content negotiation and store the accepted info on the request
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg # Determine the API version, if versioning is in use.
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme # Ensure that the incoming request is permitted
# 实现认证
self.perform_authentication(request)
# 检查权限
self.check_permissions(request)
self.check_throttles(request)

2、check_permissions()

 def check_permissions(self, request):
"""
Check if the request should be permitted.
Raises an appropriate exception if the request is not permitted.(检查是否应该允许请求。
      如果不允许请求,则引发适当的异常)
"""
# 权限列表,self.get_permissions() = MyPermission(),调用其中的 has_permission() 方法
for permission in self.get_permissions():
if not permission.has_permission(request, self):
self.permission_denied(
request, message=getattr(permission, 'message', None)
)

从上面可以看到其实权限认证,主要是调用 has_permission() 方法,若我们自定义权限类,只需实现这个方法即可。

self.get_permissions() 其本质是在定义权限类对象列表:[MyPermission(), ],具体可见 3

  • has_permission() 返回 True,即有权限访问,则不执行 self.permission_denied()
  • 若访问 False,即无权访问,则执行 self.permission_denied(),在其中返回的错误信息就是 message 所定义的,因此我们也可以自定义 message 的内容。

3、get_permissions()

def get_permissions(self):
"""
Instantiates and returns the list of permissions that this view requires.
实例化并返回此视图所需的权限列表。
"""
# permission_classes = [MyPermission, ],返回对象列表
return [permission() for permission in self.permission_classes]

源码流程图

总结

  • 自定权限类,需继承 BasePermission
  • 类中必须实现 has_permission() 方法
  • 全局定义权限(可设置 settings),局部视图类不设置权限认证,可设置 permission_classes = []

rest framework 权限的更多相关文章

  1. Django REST framework - 权限和限制

    目录 Django REST framework 权限和限制 (你能干什么) 设置权限的方法 案例 第一步: 定义一个权限类 第二步: 使用 视图级别 全局级别设置 --- 限制 (你一分钟能干多少次 ...

  2. Django rest framework ---- 权限

    Django rest framework ---- 权限 添加权限 api/utils文件夹下新建premission.py文件,代码如下: message是当没有权限时,提示的信息 # FileN ...

  3. django rest framework权限和认证

    Django rest framework之权限 一.Authentication用户认证配置 1.四种验证及官网描述: BasicAuthentication 此身份验证方案使用HTTP基本身份验证 ...

  4. Django rest framework 权限操作(源码分析)

    知识回顾http://www.cnblogs.com/ctztake/p/8419059.html 这一篇是基于上一篇写的,上一篇谢了认证的具体流程,看懂了上一篇这一篇才能看懂, 当用户访问是 首先执 ...

  5. Django REST framework —— 权限组件源码分析

    在上一篇文章中我们已经分析了认证组件源码,我们再来看看权限组件的源码,权限组件相对容易,因为只需要返回True 和False即可 代码 class ShoppingCarView(ViewSetMix ...

  6. django的rest framework框架——认证、权限、节流控制

    一.登录认证示例 模拟用户登录,获取token,当用户访问订单或用户中心时,判断用户携带正确的token,则允许查看订单和用户信息,否则抛出异常: from django.conf.urls impo ...

  7. DRF 权限和频率

    Django Rest Framework 权限组件 DRF的权限 权限组件源码解析 我们之前说过了DRF的版本和认证~也知道了权限和频率跟版本认证都是在initial方法里初始化的~~ 其实我们版本 ...

  8. python测试开发django-rest-framework-61.权限认证(permission)

    前言 用户登录后,才有操作当前用户的权限,不能操作其它人的用户,这就是需要用到权限认证,要不然你登录自己的用户,去操作别人用户的相关数据,就很危险了. authentication是身份认证,判断当前 ...

  9. python 全栈之路

    目录 Python 全栈之路 一. Python 1. Python基础知识部分 2. Python -函数 3. Python - 模块 4. Python - 面对对象 5. Python - 文 ...

随机推荐

  1. unigui中TUniDBEdit的OnEndDrag问题

    非常奇怪,unigui中TUniDBEdit未发布OnEndDrag属性,包括其子类:TUniDBNumberEdit.TUniDBFormattedNumberEdit.而其他数据感知组件都有OnE ...

  2. Netty使用LineBasedFrameDecoder解决TCP粘包/拆包

    TCP粘包/拆包 TCP是个”流”协议,所谓流,就是没有界限的一串数据.TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TC ...

  3. Hibernate和Struts分页查询

    分页查询数据库方法 /** * 分页查询方法 * @param sql,pageNO,maxResult * @return List */ public List<Object> que ...

  4. Spark-Spark setMaster & WordCount Demo

    Spark setMaster源码 /** * The master URL to connect to, such as "local" to run locally with ...

  5. Source not found The source attachment does not contain the source for the file MethodBeforeAdvice.class

  6. vps 虚拟机 云服务器

    vps :wxmp 03服务器 虚拟主机: 万网免费主机 云服务器:wxmp阿里云

  7. asp.net中异步调用WebService(异步页)[转]

    由于asp2.0提供了异步页的支持使异步调用WebService的性能有了真正的提升.使用异步页,首先要设置Async="true",异步页是在Prerender和Prerende ...

  8. 是否可以重定向到 WEB-INFO 下的页面?

    redirect的路径一定不能在WEB-INF路径下,因为redirect是相当于用户直接访问了路径,而用户不能访问WEB-INF目录下的文件,只有程序内部转发的时候才能转发到WEB-INF下的JSP ...

  9. 开发人员需要具备的DBA技术

    背景 在一些小公司或者部门里,通常很少有专门的DBA职位.这时候就需要我们这些程序员充当业余DBA的作用,去监测和维护数据库性能.本文的目的是帮助非DBA专业的开发人员如何定位和解决日常出现数据库问题 ...

  10. PHP 使用header函数设置HTTP头的示例解析 表头

    PHP 使用header函数设置HTTP头的示例解析 表头 //定义编码 header( 'Content-Type:text/html;charset=utf-8 '); //Atom header ...