繁体   English   中英

在 DRF 中拒绝权限时返回自定义消息

[英]Returning custom message when a permission is denied in DRF

Django REST Framework一篇关于权限的优秀文档 我已经能够使用预制的权限类,也可以构建我自己的权限类。

但是,在某些 API 方法中,“权限被拒绝”一般消息对用户来说信息量不大。 例如,如果用户已通过身份验证但帐户已过期,最好让用户知道他的帐户已过期,而不仅仅是权限被拒绝错误。

根据文档,在构建自定义权限类时,您可以返回TrueFalse 但是,如上所述,我想向用户显示更多信息。 如何做到这一点?

从 DRF 3.2.0 开始,您只需要添加一个 message 属性:

from rest_framework import permissions

class CustomerAccessPermission(permissions.BasePermission):
    message = 'Adding customers not allowed.'

    def has_permission(self, request, view): 

从 DRF 文档中查看: http : //www.django-rest-framework.org/api-guide/permissions/#custom-permissions

来自DRF

您可以简单地添加message属性。

from rest_framework import permissions

class IsSuperUserPermission(permissions.BasePermission):
    message = 'User is not superuser'

    def has_permission(self, request, view):
        return self.request.user.is_superuser

它将返回一个带有 key detaildict ,如下所示:

{
    'detail': 'User is not superuser'
}

但是,例如,如果您希望dict键不是detail而是errors ,那么return错误 DRF 的方式将是相同的。

我们可以set message attribute不是string而是dict ,如下所示:

class IsSuperUserPermission(permissions.BasePermission):
    message = {'errors': ['User is not a superuser']}

    def has_permission(self, request, view):
        self.message['errors'].clear()
        return self.request.user.is_superuser

在这种情况下,错误将是:

{
    'errors': ['User is not a superuser']
}

当未授予许可时,我将引发自定义响应的异常。 它适用于 djangorestframewor(3.10.1) 和 django(2.2.3)。

from rest_framework.permissions import BasePermission
from rest_framework.exceptions import APIException
from rest_framework import status


class IsLogin(BasePermission):
    """
    Allows access only to authenticated users.
    """

    def has_permission(self, request, view):
        if request.email:
            return True
        raise NeedLogin()


class NeedLogin(APIException):
    status_code = status.HTTP_403_FORBIDDEN
    default_detail = {'error': True, 'message': 'need login'}
    default_code = 'not_authenticated'

默认情况下,它由默认异常处理程序处理,并引发标准消息 - https://github.com/tomchristie/django-rest-framework/blob/2eb9107b875972e442ed73eef0e653fd4480d873/rest_framework/views.py#L82

但是,您可以在 DRF 的设置中设置自己的EXCEPTION_HANDLER ,并处理PermissionDenied异常以返回您想要的消息。

请参阅http://www.django-rest-framework.org/api-guide/settings/ 上的说明

我在使用 DRF 3.9.4 时遇到了同样的问题。 作为一种解决方法,我在自定义权限类中只定义了一个简单的消息属性,并且它可以工作。 我猜你也可以使用getattr得到相同的结果。

class IPWhitelistPermission(permissions.BasePermission):

    def __init__(self):
        super(IPWhitelistPermission, self).__init__()
        self._client_ip = None

    def has_permission(self, request, view):
        ip = get_client_ip(request)
        ret = IPWhitelist.is_whitelisted(ip)

        if not ret:
            logger = logging.getLogger('access')
            logger.warn("Unauthorized access from IP %s" % ip)
            self._client_ip = ip
        return ret

    @property
    def message(self):
        return "This IP is not whitelisted [{}]".format(self._client_ip)

基于 Aysennoussi 的回答:

from rest_framework import permissions
From django.utils import timezone

class CustomerAccessPermission(permissions.BasePermission):
    message = 'Adding customers not allowed.'

    def has_permission(self, request, view): 
        if request.user.has_expired:
            self.message = “Your account has expired.”
            return False
        elif request.user.has_access:
            return True
        else:
            return False

如果需要,您可以发送多个自定义消息。 您可以使用GenericAPIException来做到这一点。

第 1 步:创建一个 permissions.py 文件并编写此代码。

class Check_user_permission(permissions.BasePermission):
def has_permission(self, request, view):
    if request.method in permissions.SAFE_METHODS:
        return True
    else:
        response ={
            "success": "false",
            'message': "Post request is not allowed for user from admin group",
            "status_code":403,
        }
        raise GenericAPIException(detail=response, status_code=403)

在这里, response是您要发送的 JSON 响应。

第 2 步:转到 view.py 文件并以这种方式在permission_classes列表中添加类Check_user_permission

class UserList(APIView):
    permission_classes = (IsAuthenticated, Check_user_permission)
    authentication_class = JSONWebTokenAuthentication
    ... 
    ...

现在,如果您转到端点并发送 POST 请求,您将收到此响应。

{
"success": "false",
"message": "Post request is not allowed!",
"status_code": 403
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM