簡體   English   中英

Django Djoser 令牌身份驗證不起作用

[英]Django Djoser Token Authentication not working

TLDR:登錄后如何以及在哪里獲取用戶的令牌,並將其作為 header 傳遞給所有后續使用 Django/Djoser 的受限 URL?

我正在嘗試使用 Djoser 創建用戶登錄/注冊。 在登錄后的后端,我得到了身份驗證令牌,但是當我嘗試訪問任何其他頁面(例如 /users/me)時,它說:

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

I looked online and everywhere says I need to pass the authentication token in the header but all the examples I see use Postman or curl and they just copy and paste the token into the header section. 但我想在不知道令牌的情況下使用 Django 來做到這一點。

我已經看到使用token = request.META['HTTP_AUTHORIZATION']來獲取令牌,但我不確定將它放在哪里,因為我所擁有的只是

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

在我的 urls.py 文件中,它應該為我處理所有事情,所以我的 views.py 或 models.py 中沒有任何內容

然后將令牌值傳遞為 header 我見過使用 Python 請求 package:

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 但仍然不確定如何 go 關於它。

對於每個請求,您需要包含Authorization header 和值Token <auth_token_here>

這方面的標准方法是將身份驗證令牌保存在 cookie 中。 由於您使用的是 React,因此您可以使用js-cookie庫輕松完成此操作。

當您的用戶提交登錄表單時,如果登錄成功,您的 API 應該返回要存儲為 cookie 的令牌。

然后,您可以使用保存在 cookie 存儲中的令牌發出請求。

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

將 access_token 替換為授權字典中的令牌

嘗試這個:

視圖.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)

設置.py

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM