【问题标题】:Django Djoser Token Authentication not workingDjango Djoser 令牌身份验证不起作用
【发布时间】:2021-07-01 06:20:24
【问题描述】:

TLDR:登录后如何以及在何处获取用户的令牌,并将其作为标头传递给所有后续使用 Django/Djoser 的受限 URL?

我正在尝试使用 Djoser 创建用户登录/注册。在登录后的后端,我得到了身份验证令牌,但是当我尝试访问任何其他页面(例如 /users/me)时,它说:

{
    "detail": "Authentication credentials were not provided."
}

我在网上查看,到处都说我需要在标题中传递身份验证令牌,但我看到的所有示例都使用 Postman 或 curl,他们只是将令牌复制并粘贴到标题部分。但是我想在不知道令牌的情况下使用Django来做到这一点。

我已经看到使用token = request.META['HTTP_AUTHORIZATION'] 来获取令牌,但我不确定将它放在哪里,因为我只有

urlpatterns = [
    path('', include('djoser.urls')),
    path('', include('djoser.urls.authtoken')),
]

在我的 urls.py 文件中,它应该为我处理所有事情,所以我的 views.py 或 models.py 中没有任何内容

然后将令牌值作为标头传递,我已经看到使用 Python 请求包:

import requests
response = requests.get('https://website.com/id', headers={'Authorization': 'access_token myToken'})

但又一次不知道该放在哪里。

在我的 settings.py 我有:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'api.apps.ApiConfig',
    'rest_framework',
    'rest_framework.authtoken',
    'frontend.apps.FrontendConfig',
    'register',
    'djoser',
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
}

DJOSER = {
    'LOGIN_FIELD': 'username',
    'USER_CREATE_PASSWORD_RETYPE': True,
    'SERIALIZERS': {
        'user_create': 'register.serializers.UserCreateSerializer',
        'user': 'register.serializers.UserCreateSerializer',
    }
}

我也尝试过使用基本身份验证,但由于某种原因我永远无法注销。 我要问的甚至可以从后端做吗?还是必须从客户端处理?如果是这样,我正在使用 Reactjs,但仍然不知道该怎么做。

【问题讨论】:

    标签: python django django-rest-framework token djoser


    【解决方案1】:

    对于每个请求,您需要包含 Authorization 标头和值 Token <auth_token_here>

    对此的标准方法是将身份验证令牌保存在 cookie 中。 由于您使用的是 React,因此您可以使用 js-cookie 库轻松完成此操作。

    当您的用户提交登录表单时,如果登录成功,您的 API 应返回要存储为 cookie 的令牌。

    然后您可以使用 cookie 存储中持久化的令牌发出请求。

    【讨论】:

      【解决方案2】:
      import requests
      response = requests.get('https://website.com/id', headers={'Authorization': 'token myToken'})
      

      将 access_token 替换为授权字典中的令牌

      【讨论】:

        【解决方案3】:

        试试这个:

        views.py

        from rest_framework_simplejwt.views import TokenObtainPairView
        from django.conf import settings
        
        from rest_framework import status
        from rest_framework_simplejwt.exceptions import TokenError,\
            InvalidToken
        from rest_framework.response import Response
        
        class MyTokenObtainPairView(TokenObtainPairView):
            
            def post(self, request, *args, **kwargs):
                serializer = self.get_serializer(data=request.data)
        
                try:
                    serializer.is_valid(raise_exception=True)
                except TokenError as e:
                    raise InvalidToken(e.args[0])
                   
                  # set access token in browser with Httponly cookie.
                res = Response(serializer.validated_data, status=status.HTTP_200_OK)
                access_token = serializer.validated_data['access']
                res.set_cookie("access_token", access_token, max_age=settings.SIMPLE_JWT.get('ACCESS_TOKEN_LIFETIME').total_seconds(),samesite='Lax',secure=False, httponly=True)
                
                return res
        

        urls.py

        from .views import MyTokenObtainPairView
        
        urlpatterns = [
            ......
            path('auth/', include('djoser.urls')),
            # path('auth/', include('djoser.urls.jwt')),
            
            path('auth/api/token/', MyTokenObtainPairView.as_view(), name='token_obtain_pair'),
        ]
        

        创建authentication.py

        from rest_framework_simplejwt.authentication import JWTAuthentication    
        from django.conf import settings
        
        class CookieHandlerJWTAuthentication(JWTAuthentication):
            def authenticate(self, request):
                # If cookie contains access token, put it inside authorization header
                access_token = request.COOKIES.get('access_token')
                if(access_token):
                    request.META['HTTP_AUTHORIZATION'] = '{header_type} {access_token}'.format(
                        header_type=settings.SIMPLE_JWT['AUTH_HEADER_TYPES'][0], access_token=access_token)
        
                return super().authenticate(request)
        

        settings.py

        REST_FRAMEWORK = {
            
            'DEFAULT_PERMISSION_CLASSES': [
                'rest_framework.permissions.IsAuthenticated',
            ],
            'DEFAULT_AUTHENTICATION_CLASSES': (
                'myproject_name.authentication.CookieHandlerJWTAuthentication',
            )
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-12-15
          • 1970-01-01
          • 2020-02-25
          • 1970-01-01
          • 2019-02-20
          • 1970-01-01
          • 2018-06-08
          • 2013-12-02
          相关资源
          最近更新 更多