Django Rest Framework(三) 之权限认证及源码流程
权限认证的方法流程与用户认证的方法流程基本一样,也包括全局与局部认证,内部认证等
内置的权限认证类
from rest_framework.permissions import BasePermission #默认基础认证类 class BasePermission(object): def has_permission(self, request, view): return True def has_object_permission(self, request, view, obj): return True #允许所有人 class AllowAny(BasePermission): def has_permission(self, request, view): return True
源码流程
self.dispatch下的initial方法
def initial(self, request, *args, **kwargs): 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)
self.check_permissions函数源码
def check_permissions(self, request): for permission in self.get_permissions(): #首先去自定义的views里查找有没有这个get_permission方法,没有去父类(APIView)找
if not permission.has_permission(request, self): #这里红色字体为自定义时必须的函数名 self.permission_denied( request, message=getattr(permission, 'message', None) #这里message为认证失败时的提示信息,可在views里自定义 )
父类(APIView)下的 get_permissions方法,
def get_permissions(self): return [permission() for permission in self.permission_classes] #首先去自定义的views下去找有没有 permission_classes配置,没有继续从父类(APIView)下找
父类里的设置(在rest_framework下的settings.py里设置,获取相关的认证的实例化对象)
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES #这里即可定义全局的权限类,同样可以再settings里定义设置
定义全局与局部权限类
项目目录 settings.py
#utils为自定义创建的目录,用来存放用户认证、权限认证的文件,auth为自己定义创建的认证的文件,Authencation和Permission为自定义的认证函数
import utils REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES":['utils.auth.Authication'], #自定义用户认证的类 "DEFAULT_PERMISSION_CLASSES":['utils.auth.Permission'] #自定义权限认证类 }
此时,就定义了全局的权限认证类,如果要定义局部的权限认证类,同定义局部用户认证的类的方法一样,在相应的函数下加上
permission_classes = [MyPermission,] #MyPermission为自定义权限认证的类名,如果不认证,写空列表即可
如果在views.py里写了,就不会去全局配置文件里加载这个配置
自定义权限认证示例
from django.shortcuts import render,HttpResponse from django.http import JsonResponse from rest_framework.views import APIView from rest_framework.request import Request # Create your views here. from api_test import models import time,hashlib from rest_framework import exceptions from rest_framework.authentication import BaseAuthentication #内置的用户认证的类
from rest_framework.permissions import BasePermission #内置的权限认证的类
#范例数据 order_dict = { 1:{ "name":"apple", 'price':'15', 'addr':'bj', 'date':'2018-06-01' }, 2:{ "name":"tomato", 'price':'5', 'addr':'bj', 'date':'2018-06-01' } }
#自定义用户认证的类 class Authication(BaseAuthentication):
'''获取token进行用户认证 '''
#self.dispatch() def authenticate(self,request): current_token = request._request.GET.get('token') obj_token = models.UserToken.objects.filter(token=current_token).first() if not obj_token: raise exceptions.AuthenticationFailed("用户认证失败") #在rest_framework内部会将这两个字段赋值给request,以后供后续操作使用,实现原理看用户认证流程 return (obj_token.user,obj_token) def authenticate_header(self, *args): pass
#自定义权限认证类 class MyPermission(BasePermission):
message = "权限认证失败" #自定义认证失败提示信息, def has_permission(self,request,view): if request.user.user_type != 3: return False return True def md5(user):
'''生成加密的token'''
ctime = str(time.time()) m = hashlib.md5(bytes(user,encoding="utf-8")) m.update(bytes(ctime,encoding="utf-8")) return m.hexdigest()
class AuthView(APIView): ''' 用户登录认证,生成token ''' def post(self,request,*args,**kwargs): ret = {'code':10000,'msg':None} try: user = request._request.POST.get("username") #因为这里继承的Apiview,经过处理后的request,需要通过request._request才能获取原生request内的值,具体看Request函数 pwd = request._request.POST.get("password") obj = models.UserInfo.objects.filter(username=user,password=pwd).first() if not obj: ret['code'] = 10001 ret['msg'] = "用户名密码错误" #如果用户不存在,则创建token,如果用户存在,则更新token token = md5(user) models.UserToken.objects.update_or_create(user=obj,defaults={'token':token}) ret['token'] = token except Exception as e: ret['code'] = 10002 ret['msg'] = "请求异常" return JsonResponse(ret) class OrderView(APIView): ''' 订单业务接口(只有超级用户可访问) ''' # self.dispatch authentication_classes = [Authication,] permission_classes = [MyPermission,] #加载认证的类,原理看认证流程,与用户认证流程一样
def get(self,request,*args,**kwargs): print (request.user,request.auth) #打印用户信息 ret = {'code': 10000, 'msg': None} try: ret['data'] = order_dict except Exception as e: pass return JsonResponse(ret) def post(self,request,*args,**kwargs): pass def put(self,request,*args,**kwargs): pass def delete(self,request,*args,**kwargs): pass

浙公网安备 33010602011771号