django --权限认证与自定义响应结果(drf异常类)

django --权限认证与自定义响应结果(drf异常类),第1张

django --权限认证与自定义响应结果(drf异常类)

settings配置

REST_frameWORK = {
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
    # 配置默认页面大小
    'PAGE_SIZE': 10,
    # 配置默认的分页类
    'DEFAULT_PAGINATION_CLASS': 'backstage.helps.MyPageNumberPagination',

    # 配置异常处理器
    # 'EXCEPTION_HANDLER': 'api.exceptions.exception_handler',
    'EXCEPTION_HANDLER': 'backstage.utils.exception_handler',  # 替换为自定义的路径

    # 配置默认解析器
    # 'DEFAULT_PARSER_CLASSES': (
    # 'rest_framework.parsers.JSONParser',
    # 'rest_framework.parsers.FormParser',
    # 'rest_framework.parsers.MultiPartParser',
    # ),

    # 配置默认限流类
    # 'DEFAULT_THROTTLE_CLASSES': (),

    # 配置默认授权类
    # 'DEFAULT_PERMISSION_CLASSES': (
    # 'rest_framework.permissions.IsAuthenticated',
    # ),

}

重写异常

import datetime

import jwt
from jwt import InvalidTokenError
from redis import RedisError
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from django_filters import filterset
from rest_framework.authentication import baseAuthentication
from rest_framework.exceptions import AuthenticationFailed, APIException

from backstage.models import Data, BackstageUser
from express import settings

import threading

from express.settings import SECRET_KEY

from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework import status
from django.db import DatabaseError


class baseAuthException(Exception):
    '''自定义权限异常'''

    def __init__(self, msg):
        self.msg = msg
        super().__init__(self, msg)

    def __str__(self):
        return str(self.msg)

    def __call__(self, *args, **kwargs):
        return str(self.msg)


def exception_handler(exc, context):
    """
    自定义异常处理
    :param exc: 别的地方抛的异常就会传给exc
    :param context: 字典形式。抛出异常的上下文(即抛出异常的出处;即抛出异常的视图)
    :return: Response响应对象
    """
    # 调用drf框架原生的异常处理方法,把异常和异常出处交给他处理,如果是序列化器异常就直接处理,处理之后就直接返回
    response = drf_exception_handler(exc, context)
    print('222', response)
    print('111', exc)
    # 如果响应为空表示不是序列化器异常,补充数据库异常 和 认证异常
    if response is None:
        if isinstance(exc, DatabaseError) or isinstance(exc, RedisError):
            # 数据库异常
            response = Response({'msg': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)

        elif isinstance(exc, baseAuthException):
            response = Response({'code': 500, 'msg': '无效的令牌或令牌已过期,请重新登录'})

        # --- 未捕获则直接报错

    return response


class LoginRequiredAuthentication(baseAuthentication):
    """登录认证"""

    # 如果用户身份验证成功需要返回一个二元组(user, token)
    def authenticate(self, request):
        token = request.meta.get('HTTP_TOKEN')
        if token:
            try:
                print('进入权限认证')
                payload = jwt.decode(token, SECRET_KEY)
                user = BackstageUser()
                print(f'解析参数-->{payload}')
                user.userid = payload['userid']
                user.is_authenticated = True
                return user, token
            except InvalidTokenError:
                raise baseAuthException('请提供用户身份令牌')
        raise AuthenticationFailed('请提供用户身份令牌')


class SingletonType(type):
    '''多线程(元类单例)'''
    _instance_lock = threading.Lock()

    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            with SingletonType._instance_lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = super(SingletonType, cls).__call__(*args, **kwargs)
        return cls._instance

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5689667.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存