Django REST framework之版本、认证、权限、访问控制
安装与配置
安装:
pip install djangorestframework
pip install markdown # 可选依赖包
pip install django-filter # 可选依赖包
配置
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'ApiView',
'rest_framework', # 注册
]
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning', # /api/v1/users/ 版本配置
'DEFAULT_VERSION':'v1', # 默认版本
'ALLOWED_VERSIONS':['v1','v2'], # 可用版本
'VERSION_PARAM':'version', # 版本参数
'DEFAULT_AUTHENTICATION_CLASSES':['ApiView.auth.AuthClass.Auth',], # 全局验证
'UNAUTHENTICATED_USER':None, # 匿名,request.user
'UNAUTHENTICATED_TOKEN':None, # 匿名,request.auth
'DEFAULT_PERMISSION_CLASSES':['ApiView.permission.PermissionClass.VipPermission',], # 全局权限
'DEFAULT_THROTTLE_CLASSES':['ApiView.throttle.ThrottleClass.UserThrottle',], # 全局频率限制
'DEFAULT_THROTTLE_RATES':{
'anonymous':'3/m', # 匿名用户3次/分钟
'user':'10/m', # 登陆用户10次/分钟
},
'UNICODE_JSON': False, # 编码格式
}
基本使用
目录格式:

一、models.py:数据库创建
from django.db import models # Create your models here. class UserInfo(models.Model): user_type_choices = ( ('普通用户',1), ('会员用户',2), ('管理员',3), ) user_type = models.CharField(choices=user_type_choices,max_length=32) username = models.CharField(max_length=32,unique=True) password = models.CharField(max_length=64) def __str__(self): return self.username class AuthToken(models.Model): user = models.OneToOneField(to=UserInfo,on_delete=models.CASCADE) token = models.CharField(max_length=255)
二、views.py:视图文件内容
from django.http import JsonResponse from rest_framework.views import APIView from ApiView import models from ApiView.util.tools import Utools class AuthView(APIView): """ 用于用户登陆 """ authentication_classes = [] permission_classes = [] from ApiView.throttle.ThrottleClass import AuthThrottle throttle_classes = [AuthThrottle, ] def post(self, request,*args,**kwargs): ''' 登陆 :param request: :return: ''' ret = {'code': 1000, 'msg': None} try: user = request._request.POST.get('username') pwd = request._request.POST.get('password') obj = models.UserInfo.objects.filter(username=user,password=pwd).first() if not obj: ret['code'] = 1001 ret['msg'] = "用户名或密码错误" # 为用户创建token token = Utools.md5(user) models.AuthToken.objects.update_or_create(user=obj,defaults={'token':token}) ret['msg'] = '认证成功' ret['token'] = token except Exception as e: ret['code'] = 1002 ret['msg'] = "登陆请求异常" return JsonResponse(ret) # 模拟订单数据 order_dict = { 1:{ 'name':'苹果', 'price':5, 'content':'这是一个苹果' }, 2:{ 'name':'香蕉', 'price':7, 'content':'这是一个香蕉' }, } class OrderView(APIView): """ 订单相关业务 """ def get(self, request,*args,**kwargs): ret = {'code': 1000, 'msg': None,'data':None} try: ret['data'] = order_dict except Exception as e: pass return JsonResponse(ret)
三、版本:version.py
from django.shortcuts import render,HttpResponse from django.urls import reverse from rest_framework.views import APIView from rest_framework.request import Request # Create your views here. # 自定义 # class ParamVersion(BaseVersioning): # def determine_version(self, request, *args, **kwargs): # version = request.query_params.get('version') # return version class UsersView(APIView): def get(self,request,*args,**kwargs): print(request.version) # 获取版本 print(request.versioning_scheme) # 获取处理版本的对象 # rest_framework 反向生成url print(request.versioning_scheme.reverse(viewname='usersss',request=request)) # django 自带反向生成url print(reverse(viewname='userspath',kwargs={'version':request.version})) return HttpResponse('用户列表')
四、登陆认证:AuthClass.py
from rest_framework.exceptions import AuthenticationFailed from rest_framework.authentication import BaseAuthentication from ApiView import models class Auth(BaseAuthentication): """ 认证控制 """ def authenticate(self, request): token = request._request.GET.get('token') token_obj = models.AuthToken.objects.filter(token=token).first() if not token_obj: raise AuthenticationFailed({'code': 1001, 'error': '认证失败'}) # 在内部将这两个字段赋值给request.user和request.auth return (token_obj.user,token_obj) def authenticate_header(self,request): pass class AnonymousAuth(BaseAuthentication): def authenticate(self, request): pass def authenticate_header(self,request): pass
五、权限认证:PermissionClass.py
from rest_framework.permissions import BasePermission from ApiView import models class VipPermission(BasePermission): """ 权限控制 """ message = '无权限访问' def has_permission(self, request, view): try: if request.user.user_type == '1': return False except Exception as e: return False return True
六、访问控制(频率):ThrottleClass.py
from rest_framework.throttling import BaseThrottle,SimpleRateThrottle import time """ # 自定义 # 登陆访问控制/匿名用户 Access_record = {} class AuthThrottle(BaseThrottle): # 访问控制 def __init__(self): self.record = None self.settime = 60 # 判断频率是否达到最大限度 例子:同一IP,60秒内只能访问3次 def allow_request(self, request, view): # 获取用户ip remote_addr = self.get_ident(request) ctime = time.time() if remote_addr not in Access_record: Access_record[remote_addr] = [ctime, ] return True # 表示可以访问 self.record = Access_record.get(remote_addr) # self.record = record # 如果有记录,并且最后一个记录时间小于60秒以前 while self.record and self.record[-1] < ctime-self.settime: # 则删掉存储的时间记录 self.record.pop(-1) # 如果记录时间小于3次则添加当前时间到记录中 if len(self.record) < 3: self.record.insert(0,ctime) return True def wait(self): # 还需要等多久 ctime = time.time() return self.settime - (ctime - self.record[-1]) """ # 使用框架自带/匿名用户 class AuthThrottle(SimpleRateThrottle): scope = 'anonymous' def get_cache_key(self, request, view): return self.get_ident(request) # 其他接口访问控制 class UserThrottle(SimpleRateThrottle): scope = 'user' def get_cache_key(self, request, view): return request.user.username
六、权限认证时使用生成token的md5方法
import hashlib,time class Utools(object): """ 公共方法 """ # md5生成 @classmethod def md5(cls,user): ctime = str(time.time()) m = hashlib.md5(bytes(user, encoding='utf-8')) m.update(bytes(ctime, encoding='utf-8')) return m.hexdigest() if __name__ == '__main__': f = Utools.md5(user='bb') print(f)
注:顺序为 版本 -- 认证 -- 授权 -- 访问次数/频率

浙公网安备 33010602011771号