zoukankan      html  css  js  c++  java
  • restful知识点之三restframework认证-->权限-->频率

     

    认证、权限、频率是层层递进的关系

      权限业务时认证+权限

      频率业务时:认证+权限+频率

    局部认证方式

    from django.conf.urls import url,include
    from django.contrib import admin
    from api import views
    
    urlpatterns = [
        # url(r'^admin/', admin.site.urls),
        url(r'^auth/', views.AuthView.as_view()),
        url(r'^books/', views.booksView.as_view()),
        url(r'^books_detail/(d+)/$', views.book_detail.as_view()),
        url(r'^oderDetial/$', views.OderDetialView.as_view()),
    
    ]
    urls.py
    from rest_framework.views import APIView
    from api.models import *
    import uuid
    from django.http import JsonResponse
    from rest_framework.response import Response#渲染器
    from api.util.Myserializer import BookSerializers
    from rest_framework import exceptions#抛异常
    from rest_framework.generics import GenericAPIView
    from rest_framework.viewsets import GenericViewSet
    from rest_framework.authentication import BaseAuthentication
    
    # Create your views here.
    
    
    ORDER_DICT = {
        1:{
            'name': "媳妇",
            'age':18,
            'gender':'',
            'content':'...'
        },
        2:{
            'name': "老狗",
            'age':19,
            'gender':'',
            'content':'...。。'
        },
    }
    
    class AuthView(APIView):
        def post(self,request):
    
            ret={'code':1000,'msg':None}
            # 从前端获取用户名密码
            try:
                user=request._request.POST.get('username')
                pwd=request._request.POST.get('password')
            #     取数据库校验
                obj=User.objects.filter(name=user,pwd=pwd).first()
    
                if not obj:
                    ret['code']=1001
                    ret['msg']='用户名密码错误'
            #     登录成功生成token写入token表(如果有则更新,没有则创建)
                token=str(uuid.uuid4())
                Token.objects.update_or_create(user=obj,defaults={'token':token})
                ret['token']=token
            except Exception as e:
                ret['code']=1002
                ret['msg']='请求异常'
            return JsonResponse(ret)
    
    class Authtication(object):
        def authenticate(self,request):
            # 接收来自前端发来的token值
            token = request._request.GET.get('token')
    #         从数据库中查找
            token_obj=Token.objects.filter(token=token).first()
            if not token_obj:
                raise exceptions.AuthenticationFailed('用户认证失败')
            # 在rest_framework内部会将两个字段赋值给request,以供后续使用
            return (token_obj.user,token_obj)
        def authenticate_header(self,request):
            pass
    
    
    
    
    
    class OderDetialView(APIView):
       authentication_classes = [Authtication,]
       def get(self,request):
           ret={'code':1000,'msg':None,'data':None}
    
           ret['data']=ORDER_DICT
           return JsonResponse(ret)
    views.py
    from django.db import models
    
    # Create your models here.
    from django.db import models
    
    # Create your models here.
    
    class User(models.Model):
        name=models.CharField(max_length=32)
        pwd=models.CharField(max_length=32)
        type_choices=((1,"普通用户"),(2,"VIP"),(3,"SVIP"))
        user_type=models.IntegerField(choices=type_choices,default=1)
    
    
    class Token(models.Model):
        user=models.OneToOneField("User")
        token = models.CharField(max_length=128)
    
        def __str__(self):
            return self.token
    modesl.py

     

    postman执行:

      

    全局认证方式

    settings.py配置如下:

    REST_FRAMEWORK={
    'DEFAULT_AUTHENTICATION_CLASSES':['app02.service.auth.Authtication',
    ]
    }
    from app02.models import *
    from rest_framework import exceptions
    
    #不继承BaseAuthentication也可以
    class Authtication(object):
        def authenticate(self,request):
            token=request._request.GET.get('token')
            token_obj=UserToken.objects.filter(token=token).first()
            if not token_obj:
                raise  exceptions.AuthenticationFailed('用户认证失败')
           #rest framework内部会将这两个字段赋值给request,以供后续操作使用
            return (token_obj.user,token_obj)
    
        def authenticate_header(self, request):
                pass
    app02.service.auth.py

     认证源码分析流程:

     权限

    class permission(object):
        def has_permission(self,request,view):
            if request.user.user_type !=2:
                return True
            return False
        
        
    class OderDetialView(APIView):
       # authentication_classes = [Authtication,]
       permission_classes = [permission,]
       def get(self,request):
           ret={'code':1000,'msg':None,'data':None}
           print(request.user.user_type,
        'user表中填入的user_type类型,
        权限认证时重新封装了新的request.user(user是数据库关联字段)
    ) if request.user.user_type==2: ret['data']=ORDER_DICT return JsonResponse(ret)

     频率

    import time
    VISIT_RECORD = {}   # 格式是{id:[time2]}
    
    # 访问频率类
    class VisitThrottle(object):
        """60秒内只能访问3次"""
        def __init__(self):
            self.history = None
    
        def allow_request(self, request, view):
            # 获取用户IP
            remote_addr = request.META.get('REMOTE_ADDR')
            ctime = time.time()
            print(remote_addr)
            if remote_addr not in VISIT_RECORD:  # 如果是第一次访问,就存放访问时间以及IP地址
                VISIT_RECORD[remote_addr] = [ctime,]   # 添加到VISIT_RECORD中
                return True
            history = VISIT_RECORD.get(remote_addr)  # 不是第一次访问,先获取记录
            self.history = history
            print("111:",history)
            while history and history[-1] < ctime - 60:   # 如果最早一次访问时间超过一分钟,就删掉 去掉history and  后把while改成if,可以实现一样的功能
    # 上一行代码中while循环一直循环,如果列表history为空,循环的时候都会报错,因为找不到history[-1]这个值,所以要加上history,用来跳出循环,防止代码出错
                history.pop()
    
            if len(history) < 3:  # 不用写else,如果不小于3,会有错误处理机制,直接拒绝访问。
                history.insert(0, ctime)  # 按照索引插入元素
                return True
        def wait(self):
            ctime = time.time()
            return 60 - (ctime - self.history[-1])
  • 相关阅读:
    转发自lealii 的博客,如有侵权请通知删除
    SQL注入详解-转发
    IT实用技术资源整理
    JMeter-接口自动化之正则表达式关联
    转发自_destiny如有侵权请联系删除
    二元数组的最小值最大和
    连续区间和大于等于某个数(弱化版)
    独一无二的最小生成树
    牛客小白月赛19 弱版 C
    牛客 安徽大学新生赛 G
  • 原文地址:https://www.cnblogs.com/wanghuaqiang/p/9063023.html
Copyright © 2011-2022 走看看