>Django REST 框架有一个关于权限的优秀文档。我已经能够使用预制的权限类,并且还构建了自己的权限类。
但是,在某些 API 方法中,"权限被拒绝"通用消息对用户来说信息量不大。例如,如果用户已通过身份验证,但帐户已过期,则最好让用户知道其帐户已过期,而不仅仅是权限被拒绝错误。
根据文档,构建自定义权限类时,您可以返回True
或False
。但如上所述,我想向用户展示更多信息。如何做到这一点?
从 DRF 3.2.0 开始,您只需添加一个消息属性:
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
它将返回一个带有密钥detail
dict
,如下所示:
{
'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'
建立在Aysennoussi的答案之上:
from rest_framework import permissions
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
默认情况下,它由默认异常处理程序处理,并且它正在引发标准消息 - 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)
如果需要,您可以发送多个自定义消息。您可以使用 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
}