Django Rest Framework框架

(1)用户url传入的token认证

urls:
from django.conf.urls import url
from app01 import views

urlpatterns = [
    url(r'^dog/', views.DogView.as_view()),

]
models:

from django.db import models
class UserInfo(models.Model):
    username=models.CharField(max_length=32)
    pwd=models.CharField(max_length=128)
    token=models.CharField(max_length=64)
views:

from rest_framework.views import APIView
from rest_framework.authentication import BasicAuthentication
from rest_framework import exceptions
from rest_framework.request import Request
from .models import *class MyAuthenTication(BasicAuthentication):
    def authenticate(self,request):
        token=request._request.GET.get('token')
        # token='sfsfss123kuf3j123'
        # 获取用户名和密码,去数据库校验

        obj=UserInfo.objects.filter(token=token).first()

        if not obj:
            raise exceptions.AuthenticationFailed('用户认证失败')

        return (obj.username,token)

    def authenticate_header(self,request):
        pass

class DogView(APIView):
    authentication_classes = [MyAuthenTication, ]
    def get(self,request,*args,**kwargs):
        print(request)
        print(request.user)


        ret={
            'code':10000,
            'msg':'data'
        }
        return HttpResponse(json.dumps(ret),status=201)

    def post(self,request,*args,**kwargs):
        return HttpResponse('创建dog')

    def put(self, request, *args, **kwargs):
        return HttpResponse('更新dog')

    def delete(self, request, *args, **kwargs):
        return HttpResponse('删除dog')

 (2)认证

使用
创建类:继承BaseAuthentication; 实现:authenticate方法
返回值:
    ① None,下一认证来执行。
    ② raise exceptions.AuthenticationFailed('用户认证失败') # from rest_framework import exceptions
    ③ (元素1,元素2) # 元素1赋值给request.user; 元素2赋值给request.auth
局部使用:
    from rest_framework.authentication import BaseAuthentication,BasicAuthentication
    class UserInfoView(APIView):

      """
      订单相关业务
      """
        authentication_classes = [BasicAuthentication,]
        def get(self,request,*args,**kwargs):
          print(request.user)
          return HttpResponse('用户信息')

 全局使用:

      REST_FRAMEWORK = {
                 # 全局使用的认证类
                "DEFAULT_AUTHENTICATION_CLASSES":

                          ['api.utils.auth.FirstAuthtication',

                'api.utils.auth.Authtication', ],
                # "UNAUTHENTICATED_USER":lambda :"匿名用户"
                "UNAUTHENTICATED_USER":None, # 匿名,request.user = None
                "UNAUTHENTICATED_TOKEN":None,# 匿名,request.auth = None
                }

 源码流程
      dispatch
      封装request
      获取定义的认证类(全局/局部),通过列表生成时创建对象。
      initial
      perform_authentication
      request.user(内部循环....)

      执行CBV中的匹配到的方法

      

(3)权限

使用
    类,必须继承:BasePermission,必须实现:has_permission方法
       from rest_framework.permissions import BasePermission
       class SVIPPermission(BasePermission):
            message = "必须是SVIP才能访问"     #定义无权限时页面显示的信息
            def has_permission(self,request,view):
                 if request.user.user_type != 3:
                      return False
                 return True
返回值    
      True, 有权访问
      False,无权访问
局部 
      class UserInfoView(APIView):
             """
            订单相关业务(普通用户、VIP)
              """
             permission_classes = [MyPermission1, ]
             def get(self,request,*args,**kwargs):
                    return HttpResponse('用户信息')

全局 
      REST_FRAMEWORK = {
      "DEFAULT_PERMISSION_CLASSES":['api.utils.permission.SVIPPermission']
                    }

源码流程

      dispatch
      initial
      get_permissions获取定义的权限类(全局/局部)通过列表生成时创建对象,执行has_permission方法

      执行CBV中的匹配到的方法

(4)访问频率控制(节流)

自己实现:
      控制访问频率 
            import time
            VISIT_RECORD = {}

            class VisitThrottle(object):
                """60s内只能访问3次"""

                def __init__(self):
                    self.history = None

                def allow_request(self,request,view):
                    # 1. 获取用户IP
                    remote_addr = request.META.get('REMOTE_ADDR')
                    ctime = time.time()
                    if remote_addr not in VISIT_RECORD:
                        VISIT_RECORD[remote_addr] = [ctime,]
                        return True
                    history = VISIT_RECORD.get(remote_addr)
                    self.history = history

                    while history and history[-1] < ctime - 60:
                        history.pop()

                    if len(history) < 3:
                        history.insert(0,ctime)
                        return True

                    # return True    # 表示可以继续访问
                    # return False   # 表示访问频率太高,被限制

                def wait(self):
                    """
                    还需要等多少秒才能访问
                    :return:
                    """
                    ctime = time.time()
                    return 60 - (ctime - self.history[-1])

            class AuthView(APIView):
                """
                用于用户登录认证
                """
                authentication_classes = []
                permission_classes = []
                throttle_classes = [VisitThrottle,]

                def post(self,request,*args,**kwargs):


                    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 = 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)

内置控制频率类:

类, 继承:BaseThrottle,实现:allow_request、wait
类, 继承:SimpleRateThrottle,实现:get_cache_key、scope = "Luffy"(配置文件中的key)

  from rest_framework.throttling import BaseThrottle,SimpleRateThrottle
  class VisitThrottle(SimpleRateThrottle):
    scope = "Luffy"

    def get_cache_key(self, request, view):
      return self.get_ident(request)


  class UserThrottle(SimpleRateThrottle):
    scope = "LuffyUser"

    def get_cache_key(self, request, view):
      return request.user.username

 

  局部
  class AuthView(APIView):
    """
    用于用户登录认证
    """
    authentication_classes = []
    permission_classes = []
    throttle_classes = [VisitThrottle,] # *******************

    def post(self,request,*args,**kwargs):

      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'] = "用户名或密码错误"
        else:  # 为登录用户创建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)

  全局
    REST_FRAMEWORK = {
    "DEFAULT_THROTTLE_CLASSES":["api.utils.throttle.UserThrottle"],
    "DEFAULT_THROTTLE_RATES":{
    "Luffy":'3/m',
    "LuffyUser":'10/m',
    }
    }

 源码流程 

      dispatch
      initial
      get_throttles获取定义的节流类(全局/局部)通过列表生成时创建对象,实现类中方法

      执行CBV中的匹配到的方法

 

posted @ 2018-04-16 11:45  星雨5213  阅读(87)  评论(0)    收藏  举报