Django Rest framework 之 权限

一、权限实例

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

1、目录结构

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

在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数据库,找到对应的注册用户

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

拿到这个token发送请求

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

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

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

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

二、源码分析

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

1、进入dispath()方法

2、进入initial()方法

3、进入check_permissions()方法

4、权限类的具体操作

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

进入self.get_permissions()来看一下

4、获取所有的权限类

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

5、原生的权限类

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

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

三、总结

权限其实的流程跟之前的认证流程是一样的,认证类封装到request中,然后再调用认证类的方法,不过这里的方法返回值不再是像认证组件那样的直接返回一个认证的对象,而是返回一个True或者False值表示认证过的对象是否有某些权限再进行具体操作。
这里注意的是,在自己重写权限类的相关方法,添加自己的逻辑的时候,返回值需要是一个布尔值,Flase或者True,表示是否有权限。也可以通过全局配置和局部配置权限类。

原文地址:https://www.cnblogs.com/welan/p/10127146.html

时间: 2024-08-29 11:53:58

Django Rest framework 之 权限的相关文章

Django rest framework(2) ---权限

添加权限 (1)API/utils文件夹下新建premission.py文件,代码如下: message是当没有权限时,提示的信息 # utils/permission.py class SVIPPremission(object): message = "必须是SVIP才能访问" def has_permission(self,request,view): if request.user.user_type != 3: return False return True class M

Django REST Framework之权限组件

权限控制是如何实现的? 一般来说,先有认证才有权限,也就是用户登录后才能判断其权限,未登录用户给他一个默认权限. Django接收到一个请求,首先经过权限的检查,如果通过检查,拥有访问的权限,则予以放行,进入到视图处理.如果没有通过检查,不会进入视图层,直接返回前端相应信息. 使用权限控制 权限控制类: class MyPermission(BasePermission): message = "您没有权限" def has_permission(self, request, view

Django Rest Framework源码剖析(二)-----权限

一.简介 在上一篇博客中已经介绍了django rest framework 对于认证的源码流程,以及实现过程,当用户经过认证之后下一步就是涉及到权限的问题.比如订单的业务只能VIP才能查看,所以这时候需要对权限进行控制.下面将介绍DRF的权限控制源码剖析. 二.基本使用 这里继续使用之前的示例,加入相应的权限,这里先介绍使用示例,然后在分析权限源码 1.在django 项目下新建立目录utils,并建立permissions.py,添加权限控制: class MyPremission(obje

Django Restful Framework【第三篇】认证、权限、限制访问频率

一.认证 认证请求头 views.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.authentication import BaseAuthentication from rest_framework.permissions import

Django REST framework - 权限和限制

目录 Django REST framework 权限和限制 (你能干什么) 设置权限的方法 案例 第一步: 定义一个权限类 第二步: 使用 视图级别 全局级别设置 --- 限制 (你一分钟能干多少次?)**好像有点污~~ ### 第一步: 自定义限制类 第二步: 使用 嫌麻烦的话,还可以使用内置限制类,哈哈~ Django REST framework 权限和限制 (你能干什么) 与身份验证和限制一起,权限确定是应该授予还是拒绝访问请求. 在允许任何其他代码继续之前,权限检查始终在视图的最开始

Django rest framework ---- 权限

Django rest framework ---- 权限 添加权限 api/utils文件夹下新建premission.py文件,代码如下: message是当没有权限时,提示的信息 # FileName : permission.py # Author : Adil # DateTime : 2019/7/30 5:14 PM # SoftWare : PyCharm from rest_framework.permissions import BasePermission class SV

利用 Django REST framework 编写 RESTful API

利用 Django REST framework 编写 RESTful API Updateat 2015/12/3: 增加 filter 最近在玩 Django,不得不说 rest_framework 真乃一大神器,可以轻易的甚至自动化的搞定很多事情,比如: 自动生成符合 RESTful 规范的 API 支持 OPTION.HEAD.POST.GET.PATCH.PUT.DELETE 根据 Content-Type 来动态的返回数据类型(如 text.json) 生成 browserable

Python【第二十四课】Django rest framework

本节内容 Django rest framework 安装 Django rest framwwork 环境配置 简单举例说明 Django中使用 rest framework 1.1 安装 Django rest framework 建立新的环境 virtualenv env source env/bin/activate 安装 djangorestframework 模块 pip install django pip install djangorestframework pip insta

Django——REST framework

1. 什么是REST REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为"表征状态转移" REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态 REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为"表征状态