Django权限要求

3

我正在尝试检查一些API请求的权限。 我已经像view_company add_company等设置了auth用户、auth_user_user_permissions和auth_permissions表,但问题不在于此。问题是当我尝试使用装饰器时。

@permission_required('API.view_company', raise_exception=True)

它对我说:

AttributeError: 'CompanyDetailView' object has no attribute 'user'

很可能它正在寻找用户,因为它要检查用户权限是否有权查看公司,但我在urls.py中声明的视图(path('companies//', CompanyDetailView.as_view()))没有用户对象,因此返回属性错误消息。我该如何解决这个问题?非常感谢。
我尝试在视图类中设置示例用户,一开始可以工作,因为视图正在寻找用户对象,但我不能以这种方式使用,因为每个请求都有不同的用户。
import rest_framework
from rest_framework import status
from django.contrib.auth.models import User
from rest_framework.views import APIView
from rest_framework.response import Response
from django.contrib.auth.decorators import permission_required

class CompanyDetailView(APIView):
    @permission_required('api.view_company', raise_exception=True)
    def get(self, request, id):
        try:
            request_data = {}
            request_data['request_method'] = request.method
            request_data['id'] = id
            companies = Company.objects.get(id=id)
            status = rest_framework.status.HTTP_200_OK
            return Response(companies, status)

bla bla bla

url line was =

path('companies/<int:id>/', CompanyDetailView.as_view()),

我的错误信息是:AttributeError: 'CompanyDetailView'对象没有属性'user' 当我进行调试,看到request.user.has_perm('view_company')返回false,但是API仍然会给出响应,它应该说您无权查看公司。

分享Company的模型 - Usman Maqbool
从django.db导入models 从api.models.base导入BaseModelclass Company(BaseModel): name = models.CharField(max_length=50, null=True) code = models.CharField(max_length=5, null=True, unique=True) is_active = models.BooleanField(default=True) - kaanozbudak
如果你说要在你的公司模型中添加用户关系,我无法这样做。它应该检查请求的用户,因为主要目的是,某个人使用GET方法请求该API时,这个人能否看到或不看到,重要的是这个人的用户权限。 - kaanozbudak
3个回答

3

谢谢,但是我应该在def get之前设置我的装饰器吗? - kaanozbudak
不,装饰器不再必要了。但是我认为我的答案不正确,因为它是关于普通的Django视图,而不是Django Rest Framework。 - Bastian
很抱歉,对我来说仍然不起作用,因为permission_classes = [IsAuthenticated] raise_exception = True permission_required = ('api.view_company', 'api.add_company')并且我还使用了CompanyDetailView(APIView, PermissionRequiredMixin)。 - kaanozbudak
当我进行调试并且看到 request.user.has_perm('view_company') 返回为假时,但是 API 仍然会返回响应,它应该显示"您没有权限查看公司"。 - kaanozbudak

3
Django视图和Django Rest框架视图的机制有点不同,这就是为什么会出现错误信息的原因。permission_required 会尝试访问视图中的user 字段,并使用has_perm 方法检查用户权限。但APIView内部没有user字段。

为了解决这个问题,您可以使用由Django Rest Framework提供的权限来限制访问。
但如果您仍想使用Django内置的权限来限制对视图的访问,则可以创建一个权限类,该类将使用has_perm来检查用户权限。例如:
from rest_framework import permissions
from rest_framework import exceptions

class ViewCompanyPermission(permissions.BasePermission):
    def has_permission(self, request, view):
        if not request.user.has_perm('api.view_company'):
            raise exceptions.PermissionDenied("Don't have permission")
        return True

您可以通过 permission_classes 字段将其应用在您的视图上:
class CompanyDetailView(APIView):
    permission_classes = (ViewCompanyPermission, )
    def get(self, request, id):
        try:
            request_data = {}
            request_data['request_method'] = request.method
            request_data['id'] = id
            companies = Company.objects.get(id=id)
            status = rest_framework.status.HTTP_200_OK
            return Response(companies, status)

如果您想要复制permission_required的行为,可以按照以下步骤进行操作:
from rest_framework import permissions
from rest_framework import exceptions

def permission_required(permission_name, raise_exception=False):
    class PermissionRequired(permissions.BasePermission):
        def has_permission(self, request, view):
            if not request.user.has_perm(permission_name):
                if raise_exception:
                    raise exceptions.PermissionDenied("Don't have permission")
                return False
            return True
    return PermissionRequired

然后您可以像这样使用它:

class CompanyDetailView(APIView):
    permission_classes = (permission_required("api.view_company", raise_exception=True), )
    # ...

1

根据permission_required描述,应该将此装饰器用于函数视图,其中第一个参数是request,而你尝试将其应用于类方法,而在你的情况下,第一个参数是self,即CompanyDetailView的实例,因此会出现错误。你应该使用另一种方式来检查权限。

您可以在此处阅读一些示例:decorators-on-django-class-based-views


首先,非常感谢,实际上我看到了那些问题和答案,但我觉得我的情况与需要登录的事情不同。我已经通过令牌控制系统检查了用户是否已登录,每个请求都必须带有特定的令牌,当他们将凭据发布到 /auth_token 的 URL 时,他们可以获得令牌。我在使用 @permission_required 装饰器时遇到了问题。 - kaanozbudak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接