需要 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 需要一个或其他权限