Django Djoser 令牌身份验证不起作用
Django Djoser Token Authentication not working
TLDR:登录后如何以及在何处获取用户令牌并将其作为 header 传递到所有使用 Django/Djoser 的后续受限 URL?
我正在尝试使用 Djoser 创建一个用户 login/sign。在登录后的后端,我获得了身份验证令牌,但是当我尝试访问任何其他页面(例如 /users/me)时,它显示:
{
"detail": "Authentication credentials were not provided."
}
我上网看了看,到处都说我需要在 header 中传递身份验证令牌,但我看到的所有示例都使用 Postman 或 curl,他们只是将令牌复制并粘贴到 header部分。但是我想在不知道令牌的情况下使用Django来完成。
我见过使用 token = request.META['HTTP_AUTHORIZATION']
来获取令牌,但我不确定将它放在哪里,因为我只有
urlpatterns = [
path('', include('djoser.urls')),
path('', include('djoser.urls.authtoken')),
]
在我的 urls.py 文件中,它应该为我处理所有事情,所以我的 views.py 或 models.py
中没有任何东西
然后将令牌值作为 header 传递 我见过使用 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,但仍然不确定如何去做。
对于每个请求,您需要包含 Authorization
header 和值 Token <auth_token_here>
。
关于此的标准方法是将身份验证令牌保存在 cookie 中。
由于您使用的是 React,因此您可以使用 js-cookie
库轻松完成此操作。
当您的用户提交登录表单时,如果登录成功,您的 API 应该 return 将令牌存储为 cookie。
然后您可以使用保存在 cookie 存储中的令牌发出请求。
import requests
response = requests.get('https://website.com/id', headers={'Authorization': 'token myToken'})
将access_token替换为授权字典中的token
试试这个:
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',
)
}
TLDR:登录后如何以及在何处获取用户令牌并将其作为 header 传递到所有使用 Django/Djoser 的后续受限 URL?
我正在尝试使用 Djoser 创建一个用户 login/sign。在登录后的后端,我获得了身份验证令牌,但是当我尝试访问任何其他页面(例如 /users/me)时,它显示:
{
"detail": "Authentication credentials were not provided."
}
我上网看了看,到处都说我需要在 header 中传递身份验证令牌,但我看到的所有示例都使用 Postman 或 curl,他们只是将令牌复制并粘贴到 header部分。但是我想在不知道令牌的情况下使用Django来完成。
我见过使用 token = request.META['HTTP_AUTHORIZATION']
来获取令牌,但我不确定将它放在哪里,因为我只有
urlpatterns = [
path('', include('djoser.urls')),
path('', include('djoser.urls.authtoken')),
]
在我的 urls.py 文件中,它应该为我处理所有事情,所以我的 views.py 或 models.py
中没有任何东西然后将令牌值作为 header 传递 我见过使用 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,但仍然不确定如何去做。
对于每个请求,您需要包含 Authorization
header 和值 Token <auth_token_here>
。
关于此的标准方法是将身份验证令牌保存在 cookie 中。
由于您使用的是 React,因此您可以使用 js-cookie
库轻松完成此操作。
当您的用户提交登录表单时,如果登录成功,您的 API 应该 return 将令牌存储为 cookie。
然后您可以使用保存在 cookie 存储中的令牌发出请求。
import requests
response = requests.get('https://website.com/id', headers={'Authorization': 'token myToken'})
将access_token替换为授权字典中的token
试试这个:
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',
)
}