【问题标题】:'AnonymousUser' object has no attribute 'is_admin''AnonymousUser' 对象没有属性 'is_admin'
【发布时间】:2020-10-21 16:23:37
【问题描述】:

我正在使用 Django 2.2 和 Python 3.6。

我使用 AWS EB 部署了 Django REST 服务器,但出现以下错误。

在本地可以正常工作,但是在EB实例中出现错误。

经过我的分析,request.user在本地是正常识别的,但是在EB上却被标记为匿名用户。

我使用相同的代码,但为什么会发生这种情况?

REST_FRAMEWORK = {
    "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
    "PAGE_SIZE": 10,
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "rest_framework_simplejwt.authentication.JWTAuthentication",
    ],
}

因为是AUTHENTICATION_CLASSES的问题,我把上面的代码改成了下面的代码,但是还是报错。

REST_FRAMEWORK = {
    "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
    "PAGE_SIZE": 10,
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "rest_framework_simplejwt.authentication.JWTAuthentication",
        "rest_framework.authentication.BasicAuthentication",
        "rest_framework.authentication.SessionAuthentication",
    ],
}

错误详情

AttributeError
'AnonymousUser' object has no attribute 'is_admin'

users/permissions.py in has_permission at line 26
    def has_permission(self, request, view):
        print("=" * 50)
        print(request.user)
        print("=" * 50)
        return bool(request.user and request.user.is_admin)

时间轴

> GET /api/v1/users/ HTTP/1.1
> Host: instance.ap-northeast-2.elasticbeanstalk.com
> User-Agent: insomnia/2020.2.2
> Content-Type: application/json
> Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTkzNjA4Nzg5LCJqdGkiOiJmZGY5YmM4MWM3M2I0YTU3YmZkODg2YmU5ZWVlMGEzZCIsInVzZXJfaWQiOjN9.kLv3H7ygzVomI2DgU84I900m4CydhL48Ob86SX5IEaQ

users/models.py

class User(AbstractBaseUser, TimeStampedModel):
    objects = UserManager()

    GENDER_MALE = "male"
    GENDER_FEMALE = "female"
    GENDER_OTHER = "other"

    GENDER_CHOICES = (
        (GENDER_MALE, "Male"),
        (GENDER_FEMALE, "Female"),
        (GENDER_OTHER, "Other"),
    )

    email = models.EmailField(unique=True)
    username = models.CharField(max_length=20, unique=True)
    gender = models.CharField(max_length=5, choices=GENDER_CHOICES)
    birth = models.DateField()
    avatar = models.ImageField(upload_to="user_avatars/%Y/%m/%d", blank=True)
    is_admin = models.BooleanField(default=False)

users/views.py

from .permissions import IsSelf, IsAdminOrSelf, IsAdminUser

class UsersViewSet(ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def get_permissions(self):
        if self.action == "list":
            permission_classes = [IsAdminUser]
        elif self.action == "create" or self.action == "retrieve":
            permission_classes = [AllowAny]
        elif self.action == "destroy":
            permission_classes = [IsAdminOrSelf]
        else:
            permission_classes = [IsSelf]

users/permissions.py

from rest_framework.permissions import BasePermission


class IsSelf(BasePermission):
    def has_object_permission(self, request, view, user):
        return bool(user == request.user)


class IsAdminOrSelf(BasePermission):
    def has_object_permission(self, request, view, user):
        is_self = bool(user == request.user)
        is_admin = request.user.is_admin

        return is_self or is_admin


class IsAdminUser(BasePermission):
    """
    Allows access only to admin users.
    """

    def has_permission(self, request, view):
        print("=" * 50)
        print(request.user)
        print("=" * 50)
        return bool(request.user and request.user.is_admin)

服务器回溯

Traceback:

File "/opt/python/run/venv/local/lib64/python3.6/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/opt/python/run/venv/local/lib64/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "/opt/python/run/venv/local/lib64/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/opt/python/run/venv/local/lib64/python3.6/site-packages/django/views/decorators/csrf.py" in wrapped_view
  54.         return view_func(*args, **kwargs)

File "/opt/python/run/venv/local/lib/python3.6/site-packages/rest_framework/viewsets.py" in view
  114.             return self.dispatch(request, *args, **kwargs)

File "/opt/python/run/venv/local/lib/python3.6/site-packages/rest_framework/views.py" in dispatch
  505.             response = self.handle_exception(exc)

File "/opt/python/run/venv/local/lib/python3.6/site-packages/rest_framework/views.py" in handle_exception
  465.             self.raise_uncaught_exception(exc)

File "/opt/python/run/venv/local/lib/python3.6/site-packages/rest_framework/views.py" in raise_uncaught_exception
  476.         raise exc

File "/opt/python/run/venv/local/lib/python3.6/site-packages/rest_framework/views.py" in dispatch
  493.             self.initial(request, *args, **kwargs)

File "/opt/python/run/venv/local/lib/python3.6/site-packages/sentry_sdk/integrations/django/__init__.py" in sentry_patched_drf_initial
  258.                     return old_drf_initial(self, request, *args, **kwargs)

File "/opt/python/run/venv/local/lib/python3.6/site-packages/rest_framework/views.py" in initial
  411.         self.check_permissions(request)

File "/opt/python/run/venv/local/lib/python3.6/site-packages/rest_framework/views.py" in check_permissions
  332.             if not permission.has_permission(request, self):

File "/opt/python/current/app/users/permissions.py" in has_permission
  26.         return bool(request.user and request.user.is_admin)

Exception Type: AttributeError at /api/v1/users/
Exception Value: 'AnonymousUser' object has no attribute 'is_admin'
Request information:
USER: AnonymousUser

GET: No GET data

POST: No POST data

FILES: No FILES data

COOKIES: No cookie data

JWT 身份验证
用户/urls.py

from rest_framework.routers import DefaultRouter
from rest_framework_simplejwt import views as jwt_views

from django.urls import path

from . import views

urlpatterns = [
    path("token/", jwt_views.TokenObtainPairView.as_view(), name="token_obtain_pair"),
    path("token/refresh/", jwt_views.TokenRefreshView.as_view(), name="token_refresh"),
]

基于会话的身份验证似乎有效。

在我看来,授权标头似乎不起作用。

# code
class IsAdminUser(BasePermission):
    """
    Allows access only to admin users.
    """

    def has_permission(self, request, view):
        print("=" * 50)
        print(request.auth)
        print(request.data)
        print(request.user)
        print("=" * 50)
        return bool(request.user and request.user.is_admin)

# result in AWS EB
[Wed Jul 01 20:37:28.712785 2020] [:error] [pid 3995] ==================================================
[Wed Jul 01 20:37:28.712834 2020] [:error] [pid 3995] None
[Wed Jul 01 20:37:28.713505 2020] [:error] [pid 3995] <QueryDict: {}>
[Wed Jul 01 20:37:28.713522 2020] [:error] [pid 3995] AnonymousUser
[Wed Jul 01 20:37:28.713529 2020] [:error] [pid 3995] ==================================================

# result in localhost
System check identified no issues (0 silenced).
July 01, 2020 - 20:43:04
Django version 2.2.12, using settings 'config.settings'
Starting development server at http://127.0.0.1:9000/
Quit the server with CONTROL-C.
==================================================
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTkzNjA1MzM0LCJqdGkiOiIyOTY3ZTQ3MDEzY2Q0MDNlODQxN2VjNTNkMDU4ZDRjZiIsInVzZXJfaWQiOjF9.3czMFSzMR-g-vraPnOhhf0UCWamlIpSLuD0I1RBJOnA
<QueryDict: {}>
1 : tim
==================================================
[01/Jul/2020 20:43:13] "GET /api/v1/users/ HTTP/1.1" 200 1768

到底是什么问题..

【问题讨论】:

    标签: amazon-web-services django-rest-framework amazon-elastic-beanstalk django-rest-framework-jwt


    【解决方案1】:

    第一个问题是AnonymousUser在django中没有is_admin属性。您可以检查is_superuser 或在调用is_admin 之前检查您的用户是否已通过身份验证。请参阅How to check if a user is logged in (how to properly use user.is_authenticated)?

    关于本地和远程之间的区别,我猜您登录的是本地应用程序,而不是远程应用程序。这就是为什么AnonymousUser 在您的远程应用上被request.user 返回的原因。

    【讨论】:

    • 很抱歉,尽管将 Authorization 标头设置为 Json 类型,但仍出现错误。 Heather 正在发送:授权:Bearer {JWT}
    • 我似乎无法通过JWT Auth在部署环境中登录,但我可以从Django Admin窗口登录。我该如何解决这个问题?
    • 如果无法登录,你在Header中传入的JWT是从哪里来的? (您在第一条评论中提到了它)。可能有很多东西,也许你的 API 无法与你的后端通信?尝试在您的问题中添加更多关于网络、登录时传递的内容、服务器返回的内容等的信息。
    • 我在问题中添加了更多信息,请检查!感谢您花时间陪伴我。
    【解决方案2】:

    我遇到的问题和这个question的原因是一样的。

    这也是 AWS 论坛上的一个已知问题。

    您可以通过以下方式修复它:

    # .ebextensions/wsgihacks.config
    
    files:
      "/etc/httpd/conf.d/wsgihacks.conf":
        mode: "000644"
        owner: root
        group: root
        content: |
          WSGIPassAuthorization on
    

    原帖:https://forums.aws.amazon.com/message.jspa?messageID=376244

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-02
      • 1970-01-01
      • 1970-01-01
      • 2020-10-13
      • 2019-10-21
      • 2015-06-11
      • 1970-01-01
      相关资源
      最近更新 更多