需要 Django 权限

Posted

技术标签:

【中文标题】需要 Django 权限【英文标题】:Django Permission Required 【发布时间】:2020-01-25 16:25:12 【问题描述】:

我正在尝试检查某些 API 请求的权限。 我已经设置了 auth users 和 auth_user_user_permissions 和 auth_permissions 表,例如 view_company add_company bla bla,但问题不在于。问题是当我尝试使用装饰器时

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

它对我说

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

很可能它正在寻找用户,因为它会检查 user_permission 是否可用于查看公司,但我在 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)

呜呜呜

url 行是 =

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

我的错误信息是:AttributeError: 'CompanyDetailView' object has no attribute 'user'

当我调试时,我看到 request.user.has_perm('view_company')returned false 但仍然 api 给出响应,它假设说你不允许查看公司

【问题讨论】:

分享Company的型号 from django.db import models from api.models.base import BaseModel class 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) 如果您说将用户关系添加到您的公司模型,我不能。假设检查请求用户,因为主要目的是x人用get方法请求那个api,这个x人能不能看到,重要的是x人的用户权限 【参考方案1】:

Django Views 和 Django Rest Framework Views 的机制有点不同,这就是你收到错误消息的原因。 permission_required 将尝试访问您视图的user 字段以使用has_perm 方法检查用户权限。但是 APIView 里面没有 user 字段。

要摆脱这种情况,您可能需要使用 Django Rest Framework 提供的permissions 来限制访问。

但是如果您仍然想使用 Django 的内置权限来限制对您的视图的访问,您可以创建一个 Permission 类,该类将使用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), )
    # ...

【讨论】:

【参考方案2】:

你不能轻易地将 django 权限与 django rest 框架一起使用。

有一个关于 django-rest-framework 权限的教程:

https://www.django-rest-framework.org/api-guide/permissions/

【讨论】:

谢谢,我还是应该在我的 def get 之前设置我的装饰器 no .. 装饰器不再需要。但我认为我的答案不正确,因为它是关于普通的 django 视图,而不是关于 django rest 框架 对不起,仍然对我不起作用,因为 ``` permission_classes = [IsAuthenticated] raise_exception = True permission_required = ('api.view_company', 'api.add_company') ``` 还有我使用 CompanyDetailView(APIView, PermissionRequiredMixin) 当我调试时,我看到 request.user.has_perm('view_company') 返回 false 但仍然 api 给出响应,假设说您不允许查看公司【参考方案3】:

根据permission_required 的描述,此装饰器应用于函数视图,其中第一个参数是request,您尝试将其应用于第一个参数为self 的类方法,在您的例子中CompanyDetailView 所以你得到了错误。您应该使用另一种方式来检查权限。

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

【讨论】:

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

以上是关于需要 Django 权限的主要内容,如果未能解决你的问题,请参考以下文章

Django Rest Framework get_permissions 需要一个或其他权限

Django 权限控制初探

django的权限组件

django 权限设置-菜单显示

微信小程序和具有权限认证CSRF机制的Django服务端交流

django(权限认证)系统——第三方组件实现Object级别权限控制