Django Rest Framework(一 认证、权限、节流使用示例)

路径:api\utils\auth.py

from test_restful import models
from django.http import JsonResponse
from rest_framework.request import Request
from rest_framework import exceptions
from rest_framework.authentication import BaseAuthentication


class FirstAuthtication(BaseAuthentication):
    '''
    构建一个最基础的用户认证类,没有实际意义,仅用于熟悉它的使用方法
    '''

    def authenticate(self, request):
        token = request._request.GET.get('token')
        token_obj = models.UserToken.objects.filter(token=token).first()
        if not token_obj:
            raise exceptions.AuthenticationFailed('哎呀,没通过')
        # 返回元组,用于rest_freamwork 的后续操作
        # token_obj.user是用户类的实例 token_obj是token类的实例
        return (token_obj.user, token_obj)

    def authenticate_header(self, request):
        """
        Return a string to be used as the value of the `WWW-Authenticate`
        header in a `401 Unauthenticated` response, or `None` if the
        authentication scheme should return `403 Permission Denied` responses.
        """
        pass
utils-auth

路径:api\utils\permission.py

from rest_framework.permissions import BasePermission

class SVIP_Permission(BasePermission):
    def has_permission(self, request, view):
        """
        Return `True` if permission is granted, `False` otherwise.
        """
        if request.user.user_type == 3:
            # 用户类型是3,才有权限
            return True
        return False

    def has_object_permission(self, request, view, obj):
        """
        Return `True` if permission is granted, `False` otherwise.
        """
        return True

class VIP_Permission(BasePermission):
    message = "您没有访问权限,请购买VIP后再来"
    def has_permission(self, request, view):
        """
        Return `True` if permission is granted, `False` otherwise.
        """
        if request.user.user_type >= 2:
            # 比2大的都有权限,SVIP是3 也满足条件
            return True
        return False

    def has_object_permission(self, request, view, obj):
        """
        Return `True` if permission is granted, `False` otherwise.
        """
        return True

class Common_Permission(BasePermission):
    def has_permission(self, request, view):
        """
        Return `True` if permission is granted, `False` otherwise.
        """
        if request.user.user_type >= 1:
            # 比1大的都有权限
            return True
        return False

    def has_object_permission(self, request, view, obj):
        """
        Return `True` if permission is granted, `False` otherwise.
        """
        return True
utils-permission

路径:api\utils\permission.py

from rest_framework.throttling import BaseThrottle,SimpleRateThrottle
import time

VISIT_RECORD = {}
class Throttles_by_myself(BaseThrottle):
    '''
    节流控制类,匿名访问,基于IP进行控制
    自己写规则,完全自己写的那种
    '''

    def __init__(self):
        self.history = None

    def allow_request(self, request, view):
        # 继承BaseThrottle,就必须重写这个方法
        # 1. 获取用户IP
        #    get_ident是基类给我们提供的方法,用以获取IP
        remote_addr = self.get_ident(request)

        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:
            # 60秒 之外的值,踢出列表
            history.pop()

        if len(history) < 3:
            history.insert(0, ctime)
            # return True    # 表示可以继续访问
            # return False # 表示访问频率太高,被限制
            return True


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


class VisitThrottle(SimpleRateThrottle):
    # 基于SimpleRateThrottle类的匿名访问节流
    # 自定义 scope 和 ident 值,写在settings里边
    # soup:节流控制类的 代号
    # ident,节流控制频率 3/m  可选单位:s m h d ...
    scope = "Luffy"

    def get_cache_key(self, request, view):
        # 匿名用户以IP为key,写入缓存
        return self.get_ident(request)


class UserThrottle(SimpleRateThrottle):
    # 基于SimpleRateThrottle类的登陆用户访问节流
    scope = "LuffyUser"

    def get_cache_key(self, request, view):
        # 登陆用户以username为key,写入缓存
        return request.user.username
utils-throttle

路径:api\views.py

from django.shortcuts import render
from rest_framework.views import APIView
from test_restful import models
from django.http import JsonResponse
from rest_framework.request import Request
from rest_framework import exceptions
from rest_framework.authentication import BasicAuthentication
from rest_framework.permissions import BasePermission
from test_restful.utils import permission



def md5(user):
    import hashlib
    import time
    ctime = str(time.time())
    m = hashlib.md5(bytes(user,encoding='utf-8'))
    m.update(bytes(ctime,encoding='utf-8'))
    return m.hexdigest()

class Get_token(APIView):
    '''
    小练习:自己写的账号密码认证,通过后获取token(每次登陆都更新token)
    http://127.0.0.1:8000/api/129/get_token/
    method:POST
    body里加入 formdata
    username - hua   password - 123
    '''
    authentication_classes = [] #这个不做token认证,只核对账户密码
    premission_classes = [BasePermission,] # 默认全通过
    ret = {'code':1000,'msg':''}

    def post(self,request,*args,**kwargs):
        ret = {'code': 1000, 'msg': '','token':''}
        try:
            usr = request._request.POST.get('username')
            pwd = request._request.POST.get('password')
            obj = models.UserInfo.objects.filter(username=usr,password=pwd).first()
            if not obj:
                ret['code'] = 1001
                ret['msg'] = '用户名或密码错误'

            # 为登录用户创建token
            token = md5(usr)
            models.UserToken.objects.update_or_create(user=obj,defaults={'token':token})
            ret['msg'] = '成功获取token!每次请求都会更新'
            ret['token'] = token

        except Exception as e:
            pass

        return JsonResponse(ret)

class Authtication(object):
    '''
    构建一个最基础的用户认证类,没有实际意义,仅用于熟悉它的使用方法
    '''
    def authenticate(self,request):
        token = request._request.GET.get('token')
        token_obj = models.UserToken.objects.filter(token=token).first()
        if not token_obj:
            raise exceptions.AuthenticationFailed('哎呀,没通过')
        # 返回元组,用于rest_freamwork 的后续操作
        # token_obj.user是用户类的实例 token_obj是token类的实例
        return (token_obj.user,token_obj)

    def authenticate_header(self, request):
        """
        Return a string to be used as the value of the `WWW-Authenticate`
        header in a `401 Unauthenticated` response, or `None` if the
        authentication scheme should return `403 Permission Denied` responses.
        """
        pass

class Order(APIView):
    '''
    局部使用 类认证
    http://127.0.0.1:8000/api/129/order
    假想订单,加了认证就获取不到结果
    http://127.0.0.1:8000/api/129/order?token=ca7532bb9c112709a0f1a08203bbf069
    加了认证,必须带着token才有正确返回值
    '''
    authentication_classes = [Authtication,]
    def get(self,request,*args,**kwargs):
        ret = {'code': 1000, 'msg': ''}
        try:
            ret['data'] = '订单列表'
        except Exception as e:
            pass
        return JsonResponse(ret)


class By_utils_auth(APIView):
    # http://127.0.0.1:8000/api/129/utils_auth
    # 认证类在settings里边指定,全局有效。不想认证的话加一句  authentication_classes = [] 就行

    def get(self,request,*args,**kwargs):
        ret = {'code': 1000, 'msg': ''}
        try:
            ret['data'] = '以后都使用utils,在settings里边配置全局的用户认证'
        except Exception as e:
            pass
        return JsonResponse(ret)



#######################权限管理#############

class Common_view(APIView):
    '''
    普通用户及以上 有权查看
    http://127.0.0.1:8000/api/129/common_view/?token=9b30493482a649f11d81a93511c86bbb
    '''
    permission_classes = [permission.Common_Permission]
    def post(self,request,*args,**kwargs):
        ret = {'code': 1000, 'msg': ''}
        try:
            ret['msg'] = '普通用户视图'

            ret['request'] = str(request)
            ret['request.user'] = str(request.user)
            ret['request.auth'] = str(request.auth)
            ret['用户类型'] = str(request.user.user_type)

            print('*******',request,'*******')
            print('*******','request.user:',request.user,'*******')
            print('*******','用户类型:',request.user.user_type,'*******')
            print('*******', 'request.auth:', request.user, '*******')
        except exceptions.APIException as e:
            pass

        return JsonResponse(ret)


class VIP_view(APIView):
    '''
    普通用户及以上 有权查看
    http://127.0.0.1:8000/api/129/vip_view/?token=9b30493482a649f11d81a93511c86bbb
    '''
    permission_classes = [permission.VIP_Permission]

    def post(self,request,*args,**kwargs):
        ret = {'code': 1000, 'msg': ''}
        try:
            ret['msg'] = 'VIP级以上用户视图'
        except exceptions.APIException as e:
            pass

        return JsonResponse(ret)

class SVIP_view(APIView):
    '''
    SVIP 有权查看
    http://127.0.0.1:8000/api/129/svip_view/?token=9b30493482a649f11d81a93511c86bbb
    '''
    permission_classes = [permission.SVIP_Permission]

    def post(self,request,*args,**kwargs):
        ret = {'code': 1000, 'msg': ''}
        try:
            ret['msg'] = 'SVIP级以上用户视图'
        except exceptions.APIException as e:
            pass

        return JsonResponse(ret)


#######################频率管理/节流控制#############

class Throttle_view1(APIView):
    '''
    依靠自己实现的Throttles_by_myself类,做匿名用户节流
    http://127.0.0.1:8000/api/129/throttle_view1
    '''
    from test_restful.utils.throttle import Throttles_by_myself
    authentication_classes = []
    permission_classes = [permission.BasePermission]
    throttle_classes = [Throttles_by_myself]

    def get(self, request, *args, **kwargs):
        ret = {'code': 1000, 'msg': ''}
        try:
            ret['msg'] = '60秒内限制匿名访问3次'
        except exceptions.APIException as e:
            pass

        return JsonResponse(ret)


class Throttle_view2(APIView):
    '''
    http://127.0.0.1:8000/api/129/throttle_view2
    依靠VisitThrottle(SimpleRateThrottle)类,做匿名用户节流
    自定义 scope 和 ident 值,写在settings里边
    soup:节流控制类的 代号
    ident,节流控制频率 3/m  可选单位:s m h d ...
    '''
    from test_restful.utils.throttle import VisitThrottle
    authentication_classes = []
    permission_classes = [permission.BasePermission]
    throttle_classes = [VisitThrottle]

    def get(self, request, *args, **kwargs):
        ret = {'code': 1000, 'msg': ''}
        try:
            ret['msg'] = '一分钟内限制匿名访问3次'
        except exceptions.APIException as e:
            pass

        return JsonResponse(ret)


class Throttle_view3(APIView):
    '''
    http://127.0.0.1:8000/api/129/throttle_view3?token=ca7532bb9c112709a0f1a08203bbf069
    依靠VisitThrottle(SimpleRateThrottle)类,做匿名用户节流
    自定义 scope 和 ident 值,写在settings里边
    soup:节流控制类的 代号
    ident,节流控制频率 3/m  可选单位:s m h d ...
    '''
    from test_restful.utils.throttle import UserThrottle
    permission_classes = [permission.BasePermission]
    throttle_classes = [UserThrottle]

    def get(self, request, *args, **kwargs):
        ret = {'code': 1000, 'msg': ''}
        try:
            ret['msg'] = '登录用户,一分钟内限制访问10次'
        except exceptions.APIException as e:
            pass

        return JsonResponse(ret)
views.py

 

posted on 2018-01-24 10:51  robgo  阅读(114)  评论(0编辑  收藏  举报