Django Rest framework之权限的实现示例


Posted in Python onDecember 17, 2018

一、权限实例

在阅读本文之前请先参考django rest framework 之 认证 中关于 django rest framework 的相关内容及实例

1、目录结构

为了更好的管理各个功能组件,在django rest framework 之 认证 中我们说到可以将认证类单独的拿出来,放到其他目录下,然后导入到 views.py 文件中,在权限环节我们亦可以这么做,目录结构就变成这样

Django Rest framework之权限的实现示例

在api这个app下创建一个utils包专门用来存放相关的组件。

2、为模型类添加认证字段

我们在models.py中定义了两个模型类,分别是

from django.db import models


class UserInfo(models.Model):
  USER_TYPE = (
    (1,'普通用户'),
    (2,'VIP'),
    (3,'SVIP')
  )

  user_type = models.IntegerField(choices=USER_TYPE, default=1)
  username = models.CharField(max_length=32)
  password = models.CharField(max_length=64)

class UserToken(models.Model):
  user = models.OneToOneField(UserInfo,on_delete=models.CASCADE)
  token = models.CharField(max_length=64)

UserInfo 中通过为用户添加一个 user_type 字段来保证用户的身份,是普通用户,VIP还是SVIP,这样就可以通过用户的身份验证不同的权限。如果想要定义一个视图类,这个类中的逻辑只有超级用户才能访问。

3、具体权限认证

可以再utils中的 permissions.py 中这么写

# utils/permission.py


class SVIPPremission(object):
  message = "必须是SVIP才能访问" # 这里的message表示如果不通过权限的时候,错误提示信息

  def has_permission(self,request,view):
    if request.user.user_type != 3:
      return False
    return True


class MyPremission(object):
  # 这个权限类表示当用户为SVIP时不可通过
  def has_permission(self,request,view):
    if request.user.user_type == 3:
      return False
    return True

这里只是判断用户的 USER_TYPE 的字段,判断用户是否有权限,也可以添加其他的逻辑进行判断。

4、全局配置

在上一节的django rest framework 之 认证 的认证中,将认证类放到了 settings.py 文件中,这样会作用到视图中的每一个视图类,如果视图类想要自己进行认证,只需要重写 authentication_classes 即可,那么对于权限来说我们也可以这么做,

REST_FRAMEWORK = {
  'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.authenticate.FirstAuthenticate', 'api.utils.authenticate.MyAuthenticate'], 
  "UNAUTHENTICATED_USER": None, # 匿名,request.user = None
  "UNAUTHENTICATED_TOKEN": None,# 匿名,request.auth = None
  "DEFAULT_PERMISSION_CLASSES": ['api.utils.permission.MyPermission'], # 表示每一个视图类(只要不重写permission_classes属性),都需要SVIP的用户才能访问。
}

5、视图

在视图 view.py 中定义一个用户详情类 UserInfoView 作为测试,这里的视图和上一节的django rest framework 之 认证 是相接的。

from django.shortcuts import render, HttpResponse
from django.http import JsonResponse
from django.views import View
from rest_framework.views import APIView
from rest_framework.request import Request

from .utils import authenticate, permission
from api import models

import json


def md5(user):
  import hashlib
  import time

  # 当前时间,相当于生成一个随机的字符串
  ctime = str(time.time())

  # token加密
  m = hashlib.md5(bytes(user, encoding='utf-8'))
  m.update(bytes(ctime, encoding='utf-8'))
  return m.hexdigest()


class AuthView(APIView):
  '''用于用户登录验证'''
  authentication_classes = []   #里面为空,代表不需要认证
  permission_classes = []     #不里面为空,代表不需要权限

  def get(self, request, *args, **kwargs):
    ret = {'code': 1000, 'msg': 'success', 'name': '偷偷'}
    ret = json.dumps(ret, ensure_ascii=False)

    return HttpResponse(ret)

  def post(self,request,*args,**kwargs):
    ret = {'code':1000,'msg':None}
    try:
      user = request.POST.get('username')
      pwd = request.POST.get('password')
      print(user, pwd)
      obj = models.UserInfo.objects.filter(username=user,password=pwd).first()
      print(obj.username, obj.password)
      if not obj:
        ret['code'] = 1001
        ret['msg'] = '用户名或密码错误'
      #为用户创建token
      token = md5(user)
      #存在就更新,不存在就创建
      models.UserToken.objects.update_or_create(user=obj,defaults={'token':token})
      ret['token'] = token
    except Exception as e:
      ret['code'] = 1002
      ret['msg'] = '请求异常'
    return JsonResponse(ret)


ORDER_DICT = {
  1:{
    'name':'apple',
    'price':15
  },
  2:{
    'name':'狗子',
    'price':100
  }
}


class OrderView(APIView):
  # 用户想要获取订单,就要先通过身份认证、在全局settings.py 中已经配置
  permission_classes = []

  def get(self, request, *args, **kwargs):
    ret = {
      'code': 1024,
      'msg': '订单获取成功',
    }
    try:
      ret['data'] = ORDER_DICT
    except Exception as e:
      pass
    return JsonResponse(ret)
  

class UserInfoView(APIView):
  permission_classes = [permission.SVIPPermission]

  def get(self, request, *args, **kwargs):
    print(request.user)
    return HttpResponse('SVIP用户信息')

这里的 UserInfoView 重写了 permission_classes 属性,则不会再使用 settings.py 中关于认证类的配置。表示只有SVIP才能访问这个类的内部。

6、路由分发

在url.py中设置路由分发

from django.conf.urls import url

from api.views import AuthView, OrderView, UserInfoView


urlpatterns = [
  url(r'^api/v1/auth/$', AuthView.as_view()),
  url(r'^api/v1/order/$', OrderView.as_view()),
  url(r'^api/v1/info/$', UserInfoView.as_view()),
]

7、请求测试

Postman或者浏览器发送请求,由于我们在 setting.py 中配置了 'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.authenticate.FirstAuthenticate', 'api.utils.authenticate.MyAuthenticate'],

会对请求进行认证,所以要带这用户的 token 才能通过,进入到权限组件。

进入sqlite数据库,找到对应的注册用户

Django Rest framework之权限的实现示例

在数据库中,拿到刷新的用户的最近一次的token

Django Rest framework之权限的实现示例

拿到这个token发送请求

Django Rest framework之权限的实现示例

请求成功,则说明权限生效,也可以在将 UserInfoView 改成如下

class UserInfoView(APIView):
  permission_classes = [permission.SVIPPermission]

  def get(self, request, *args, **kwargs):
    print(request.user)
    return HttpResponse('SVIP用户信息')

在发送请求,就会发现用户不会有权限的提示信息。如下

Django Rest framework之权限的实现示例

二、源码分析

像 django rest framework 之 认证 一样进入, request 的请求流程,进入源码查看具体权限的操作

1、进入dispath()方法

Django Rest framework之权限的实现示例

2、进入initial()方法

Django Rest framework之权限的实现示例

3、进入check_permissions()方法

Django Rest framework之权限的实现示例

4、权限类的具体操作

在这里可以看到和认证中有类似的操作,获取所有的权限类,并且执行每一个权限类的 has_permission() 方法,而这个方法具体封装了我们的判断权限操作,但是 has_permission() 方法的返回值需要时 False 或者 Trueself.permission_denied(request, message=getattr(permission, 'message', None)) 说明可以在权限类中重写 message 属性,来定义权限不通过时候的提示信息。

Django Rest framework之权限的实现示例

进入 self.get_permissions() 来看一下

4、获取所有的权限类

Django Rest framework之权限的实现示例

Django Rest framework之权限的实现示例

在APIView中有定义默认的权限类,因此也可以通过全局配置的方法配置权限类。

5、原生的权限类

像认证那样, django rest framework 中也有权限类

Django Rest framework之权限的实现示例

可以根据自己的需要调用。

三、总结

权限其实的流程跟之前的认证流程是一样的,认证类封装到 request 中,然后再调用认证类的方法,不过这里的方法返回值不再是像认证组件那样的直接返回一个认证的对象,而是返回一个 True 或者 False 值表示认证过的对象是否有某些权限再进行具体操作。

这里注意的是,在自己重写权限类的相关方法,添加自己的逻辑的时候,返回值需要是一个布尔值, Flase 或者 True ,表示是否有权限。也可以通过全局配置和局部配置权限类。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python高并发异步服务器核心库forkcore使用方法
Nov 26 Python
Python多线程编程简单介绍
Apr 13 Python
python列表的常用操作方法小结
May 21 Python
详解 Python 读写XML文件的实例
Aug 02 Python
浅谈django开发者模式中的autoreload是如何实现的
Aug 18 Python
详谈Python中列表list,元祖tuple和numpy中的array区别
Apr 18 Python
解决nohup重定向python输出到文件不成功的问题
May 11 Python
点球小游戏python脚本
May 22 Python
python读取图片并修改格式与大小的方法
Jul 24 Python
Python判断一个list中是否包含另一个list全部元素的方法分析
Dec 24 Python
对python函数签名的方法详解
Jan 22 Python
Python提取支付宝和微信支付二维码的示例代码
Feb 15 Python
Python3爬虫教程之利用Python实现发送天气预报邮件
Dec 16 #Python
Python Unittest根据不同测试环境跳过用例的方法
Dec 16 #Python
python使用插值法画出平滑曲线
Dec 15 #Python
python用fsolve、leastsq对非线性方程组求解
Dec 15 #Python
python实现一组典型数据格式转换
Dec 15 #Python
python判断计算机是否有网络连接的实例
Dec 15 #Python
Django model反向关联名称的方法
Dec 15 #Python
You might like
PHP将Excel导入数据库及数据库数据导出至Excel的方法
2015/06/24 PHP
PHP遍历目录文件的常用方法小结
2017/02/03 PHP
Aster vs KG BO3 第二场2.18
2021/03/10 DOTA
多个表单中如何获得这个文件上传的网址实现js代码
2013/03/25 Javascript
选择器中含有空格在使用示例及注意事项
2013/07/31 Javascript
js+html5通过canvas指定开始和结束点绘制线条的方法
2015/06/05 Javascript
用JavaScript判断CSS浏览器类型前缀的两种方法
2015/10/08 Javascript
javascript如何实现暂停功能
2015/11/06 Javascript
jQuery插件实现静态HTML验证码校验
2015/11/06 Javascript
详解javascript事件冒泡
2016/01/09 Javascript
Javascript基础学习笔记(菜鸟必看篇)
2016/07/22 Javascript
基于JavaScript实现无限加载瀑布流
2017/07/21 Javascript
js中json对象和字符串的理解及相互转化操作实现方法
2017/09/22 Javascript
Vue 框架之动态绑定 css 样式实例分析
2018/11/14 Javascript
微信小程序蓝牙连接小票打印机实例代码详解
2019/06/03 Javascript
element-ui树形控件后台返回的数据+生成组织树的工具类
2020/03/05 Javascript
布同自制Python函数帮助查询小工具
2011/03/13 Python
在Python程序中操作MySQL的基本方法
2015/07/29 Python
Python随手笔记之标准类型内建函数
2015/12/02 Python
详解Django 中是否使用时区的区别
2018/06/14 Python
详解基于django实现的webssh简单例子
2018/07/17 Python
使用pytorch搭建AlexNet操作(微调预训练模型及手动搭建)
2020/01/18 Python
Python+OpenCV图像处理—— 色彩空间转换
2020/10/22 Python
实例教程 一款纯css3实现的数字统计游戏
2014/11/10 HTML / CSS
CSS3实现翘边的阴影效果的代码示例
2016/06/13 HTML / CSS
黑猩猩商店:The Chimp Store
2020/02/12 全球购物
美国婴儿服装购物网站:Gerber Childrenswear
2020/05/06 全球购物
加拿大著名的奢侈品购物网站:SSENSE(支持中文)
2020/06/25 全球购物
中文专业毕业生自荐信
2013/10/28 职场文书
廉洁使者实施方案
2014/03/29 职场文书
省级优秀班集体申报材料
2014/05/25 职场文书
机关作风建设剖析材料
2014/10/11 职场文书
教师群众路线教育实践活动个人对照检查材料
2014/11/04 职场文书
搞笑的婚礼主持词
2015/06/29 职场文书
自书遗嘱范文
2015/08/07 职场文书
2016廉政教育学习心得体会
2016/01/25 职场文书