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])
  • 相关阅读:
    Solution: Win 10 和 Ubuntu 16.04 LTS双系统, Win 10 不能从grub启动
    在Ubuntu上如何往fcitx里添加输入法
    LaTeX 笔记---Q&A
    Hong Kong Regional Online Preliminary 2016 C. Classrooms
    Codeforces 711E ZS and The Birthday Paradox
    poj 2342 anniversary party
    poj 1088 滑雪
    poj 2479 maximum sum
    poj 2481 cows
    poj 2352 stars
  • 原文地址:https://www.cnblogs.com/wanghuaqiang/p/9063023.html
Copyright © 2011-2022 走看看