• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

Django Rest framework之权限的实现示例

python 搞代码 4年前 (2022-01-08) 16次浏览 已收录 0个评论

这篇文章主要介绍了Django Rest framework之权限的实现示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一来源gao@daima#com搞(%代@#码@网起跟随小编过来看看吧

一、权限实例

在阅读本文之前请先参考 中关于 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 ,表示是否有权限。也可以通过全局配置和局部配置权限类。

以上就是Django Rest framework之权限的实现示例的详细内容,更多请关注gaodaima搞代码网其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Django Rest framework之权限的实现示例

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址