Django Rest Framework 中的 JWT 身份验证错误“无效签名”
Posted
技术标签:
【中文标题】Django Rest Framework 中的 JWT 身份验证错误“无效签名”【英文标题】:JWT Authentication Error "Invalid Signature" in Django Rest Framework 【发布时间】:2018-03-28 06:15:29 【问题描述】:我是 Python 和 Django REST 框架的新手,我正在尝试使用 JWT (https://jpadilla.github.io/django-rest-framework-jwt/) 配置身份验证。我可以在注册时为用户创建一个令牌,但是当我尝试通过我的 api 进行身份验证时出现“无效签名”错误。我已经在https://jwt.io/ 确认了错误。这似乎意味着我的令牌创建不正确。有什么想法吗?
这是我的配置:
from django.db import models
class User(models.Model):
first_name = models.CharField(max_length=45)
last_name = models.CharField(max_length=45)
username = models.CharField(max_length=45, unique=True)
phone = models.CharField(max_length=20)
password = models.CharField(max_length=100, blank=False, default='')
from rest_framework import serializers
from . models import User
from django.contrib.auth.hashers import make_password
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'first_name', 'last_name', 'username', 'phone',
'password')
extra_kwargs = 'password': 'write_only': True
def create(self, validated_data):
# the create method creates and saves an object in a single statement
user = User.objects.create(
first_name = validated_data['first_name'],
last_name = validated_data['last_name'],
username = validated_data['username'],
phone = validated_data['phone'],
password = make_password(validated_data['password']),
)
return user
from joyrides_api.models import User
from joyrides_api.serializers import UserSerializer
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status
from rest_framework_jwt.utils import jwt_payload_handler
from rest_framework import permissions
from rest_framework_jwt.settings import api_settings
from rest_framework.permissions import AllowAny
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
class UserList(APIView):
permission_classes = (AllowAny,)
# this method creates the user
def post(self, request, format=None):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
# the save method calls serializer's create method
user = serializer.save()
if user:
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
json = serializer.data
json['token'] = token
return Response(json, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
【问题讨论】:
【参考方案1】:您还需要指定authentication_classes
。
让它为空,它应该可以工作。
【讨论】:
我确实在我的身份验证路由上设置了 JWT 身份验证类,因为我相信这是它们的实用程序。我确实尝试在我的创建令牌路由上设置它,但仍然收到无效签名。 如果我理解正确,您成功地从这个UserList
视图获取令牌,但不能在其他视图上使用该令牌(获取“无效签名”)?
我可以从视图中获取令牌,但签名无效。我使用jwt.io 的验证器仔细检查了令牌(您可以在首页粘贴编码令牌并输出内容)。标头和有效负载正确,但签名无效。
好的,我用自己的 JWT 令牌检查了这一点。它确实说无效签名。但它可以与api一起使用。我认为“无效签名”背后的原因是我们将JWT_PUBLIC_KEY
和JWT_PRIVATE_KEY
设置为无。如果我们按照cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey
和cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey
声明密钥,我们就可以得到签名验证。
是的。我只是能够使用 createsuperuser 方法成功地对用户进行身份验证。这与我的用户模型如何与 jwt 框架交互有关。【参考方案2】:
我的问题是当我使用 django.db.model 创建方法创建用户时:
from . models import User
def create(self, validated_data):
user = User.objects.create(
first_name = validated_data['first_name'],
...
)
return user
我还没有在 django.contrib.auth.models 的 Django 用户模型中创建用户,这是 Django 和 JWT 框架用于身份验证的模型。对于初学者来说,这并不是那么简单,考虑到 JWT 与 Django 的流行(或者看起来如此),我有点惊讶这不是一个更大的问题。我想有人会告诉我我应该花更多的时间在文档上。
我离题了,优雅的解决方法是通过扩展 django.contribut.auth.models 的 AbstractUser 来自定义您的用户模型,(我相信)它将您的用户模型的相关部分链接到 Django 的模型。此处说明:https://docs.djangoproject.com/en/1.11/topics/auth/customizing/
我为启动并运行它所做的选择(尽管我计划很快切换到自定义模型)是使用 django.contrib.auth.models 的 create_user 方法将您的用户对象保存到 Django 用户模型,该方法操作相同到上面的 create 方法,除了它保存到 Django 的用户模型。
【讨论】:
【参考方案3】:我发现创建自定义用户模型时出现“无效签名”错误。我通过以下方式解决了这个问题:
-
基于 Django 的用户模型实例化模型:
``
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
.....
``
-
在 settings.py 中,使用 AUTH_USER_MODEL 指向自定义用户模型。
``
AUTH_USER_MODEL = 'user.User'
``
“user.User”指向用户应用中的用户模型。
继续生成令牌。令牌将立即生效。
【讨论】:
以上是关于Django Rest Framework 中的 JWT 身份验证错误“无效签名”的主要内容,如果未能解决你的问题,请参考以下文章
Django-Rest-Framework 中的序列化程序问题
如何从 django-rest-framework 中的文件列表中过滤图像
Django Rest Framework 中的 JWT 身份验证错误“无效签名”
django框架学习六:优化views.py文件,使用rest_framework中的APIVew和Response返回