简体   繁体   English

为什么我的 request.user 在 Django 中没有组?

[英]Why doesn't my request.user have groups in Django?

I've got an endpoint built with Django Rest Framework, to which I now want to add permissions so that only users belonging to a certain group can access an endpoint.我有一个使用 Django Rest 框架构建的端点,我现在想向其添加权限,以便只有属于特定组的用户才能访问端点。 So I'm using token based access and inspired by this example I'm trying to use the following code:所以我正在使用基于令牌的访问并受此示例的启发,我正在尝试使用以下代码:

class ReadPermission(BasePermission):
    def has_permission(self, request, view):
        return request.user.groups.filter(name=settings.GROUP_POST_DATA).exists()

class MyEndpoint(mixins.ListModelMixin, viewsets.GenericViewSet):
    permission_classes = [IsAuthenticated, ReadPermission]
    http_method_names = ['get']
    # etc

But unfortunately I get an AttributeError: 'User' object has no attribute 'groups'但不幸的是我得到一个AttributeError: 'User' object has no attribute 'groups'

Why doesn't the user object have groups?为什么用户object没有群?

Seems like you're not using or inheriting from the default Django User model (or the AbstractUser ) from django.contrib.auth.models , which have the ManyToMany relationship to Groups .似乎您没有使用或继承来自django.contrib.auth.models的默认 Django User model (或AbstractUser ),它们与Groups具有 ManyToMany 关系。

If you're using some custom User model you can simply add the PermissionsMixin from the aforementioned module to inheritance ( see docs ).如果您使用的是一些自定义User model,您只需将上述模块中的PermissionsMixin添加到 inheritance( 请参阅文档)。 And also make sure that django.contrib.auth is in your INSTALLED_APPS setting.还要确保django.contrib.auth在您的INSTALLED_APPS设置中。

The issue must be in you authentication_classes --(DRF doc) attribute (orDEFAULT_AUTHENTICATION_CLASSES settings -- (DRF doc) )问题一定出在您的authentication_classes --(DRF doc)属性(或DEFAULT_AUTHENTICATION_CLASSES设置 -- (DRF doc)

Behind the scenes, the DRF authentication classes fetch the auth user from the database and assign it to the request object only after the specified request entity (like Token , JWT Token , CSRF Token , etc) validated against the database.在幕后,DRF 身份验证类仅在针对数据库验证指定的请求实体(如TokenJWT TokenCSRF Token等)后,才从数据库中获取auth 用户并将其分配给request object 。 This validation and assigning process is happening in the authentication classes .此验证和分配过程发生在身份验证类中。

Suppose, if Django or DRF failed to identify the requested user, it will assign the AnonymousUser --(Django doc) object to the request .假设,如果 Django 或 DRF 无法识别请求的用户,它会将AnonymousUser --(Django doc) object 分配给request

Fortunately, the AnonymousUser object does have a groups and user_permissions attributes.幸运的是, AnonymousUser object 确实具有groupsuser_permissions属性。 Which means, neither request.user.groups nor request.user.user_permissions will not raise any AttributeError exceptions.这意味着, request.user.groupsrequest.user.user_permissions都不会引发任何AttributeError异常。

Coming to your case, the request.user.groups raised an exception, which indicates对于您的情况, request.user.groups引发了异常,这表明

  1. the received User object is neither settings.AUTH_USER_MODEL nor AnonymousUser收到的User object 既不是settings.AUTH_USER_MODEL也不是AnonymousUser
  2. the MyEndpoint is missing a authentication_classes attributes, hence DRF uses the DEFAULT_AUTHENTICATION_CLASSES , which may contain a custom class, which may not built properly MyEndpoint缺少authentication_classes属性,因此 DRF 使用DEFAULT_AUTHENTICATION_CLASSES ,其中可能包含自定义 class,可能未正确构建

Solution解决方案

I assume you need to use the token-based auth system, so I am using the DRF's TokenAuthentication -- (DRF doc) here.我假设您需要使用基于令牌的身份验证系统,所以我在这里使用DRF 的TokenAuthentication -- (DRF doc)

Assigning authentication_classes = (TokenAuthentication,) in the view class will definitely sets the request.user to either settings.AUTH_USER_MODEL instance or AnonymousUser .在视图 class 中分配authentication_classes = (TokenAuthentication,)肯定会将request.user设置为settings.AUTH_USER_MODEL实例或AnonymousUser

from rest_framework.authentication import TokenAuthentication


class MyEndpoint(
    mixins.ListModelMixin,
    viewsets.GenericViewSet
):
    permission_classes = [IsAuthenticated, ReadPermission]
    http_method_names = ['get']
    authentication_classes = (TokenAuthentication,)

Note笔记

The issue does not belong to the permission_classes settings, but the authentication_classes该问题不属于permission_classes设置,但属于authentication_classes


Still not solved??还没解决??

  1. Is it reproducible?它是可重现的吗? (your code snippet is working nicely in my machine, probably everyone's machine) If so, add the steps to reproduce (您的代码片段在我的机器上运行良好,可能每个人的机器上都运行良好)如果是这样,请添加重现步骤
  2. What is the value of MIDDLEWARE ? MIDDLEWARE的价值是什么? Do you have any custom one?你有定制的吗?
  3. What is the value of UNAUTHENTICATED_USER ? UNAUTHENTICATED_USER的价值是多少?

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

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