如何在注册时制作 django-rest-framework-jwt return 令牌?

How can i make django-rest-framework-jwt return token on registration?

我有一个基本的 django rest 服务,

  1. 注册一个人并
  2. 更新他的密码。

我想在上面添加 jwt 身份验证。如果我按照教程进行操作,我需要在项目的 urls.py 中添加一个名为 "api-token-auth" 的新 url。但是,我不想添加这个新的 url 并希望我的注册调用发送令牌作为响应。

这是我的代码:

serializers.py

class UserSerializer(serializers.HyperlinkedModelSerializer):
    def create(self, validated_data):
        user = User(
            username=validated_data['username']
        )
        user.set_password(validated_data['password'])
        user.save()
        return user

    def update(self, instance, validated_data):
        instance.set_password(validated_data['password'])
        instance.save()
        return instance

    class Meta:
        model = User
        fields = ('url', 'username', 'password')
        lookup_field = 'username'
        write_only_fields = ('password',)

views.py

class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.exclude(is_superuser=1)
    serializer_class = UserSerializer
    lookup_field = 'username'
  1. 要做到这一点应该怎么做?我应该在序列化程序的创建方法中调用 api-auth-token 吗?
  2. django-rest-framework-jwt 如何处理多个身份验证令牌并正确识别哪个令牌属于哪个用户?特别是当它不在数据库中存储令牌时。
  3. 如何使用此身份验证机制将我的用户限制为 view/update/delete 只有他的用户?
  4. 一般情况下,我如何使用这种身份验证机制来做任何事情。例如,如果用户想将他的名字写入 /tmp/abcd.txt。我如何确保只有经过身份验证的用户才能这样做?
  5. 这种方法有没有潜在的漏洞。如果我的应用程序要存储大量分类数据,我是否应该使用相同的代码?

问题 1:要在注册时手动生成令牌,您可以定义并使用如下方法:

import jwt
from rest_framework_jwt.utils import jwt_payload_handler

def create_token(user):
    payload = jwt_payload_handler(user)
    token = jwt.encode(payload, settings.SECRET_KEY)
    return token.decode('unicode_escape')

您可以将此方法添加到视图并在用户注册后生成令牌,并return在响应中生成令牌。

问题2:JWT token不需要存储在数据库中。您可以在 http://jwt.io/.

阅读更多关于 JWT 工作原理的信息

问题 3 和 4:使用令牌来限制对特定视图的访问,尤其是 APIView 或其子视图之一类 或 Django 提供的视图休息框架,你需要指定permission classes。例如:

from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

class ExampleView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request, format=None):
        content = {
            'status': 'request was permitted'
        }
        return Response(content)

问题 5:使用 Django Rest Framework 时的一个潜在漏洞是您从应用程序设置中设置的默认权限;例如,如果您在设置中 AllowAny,它将使所有视图都可公开访问,除非您在每个视图中明确覆盖权限 类。

已接受的答案有一些生成令牌的代码,但没有说明如何将其集成到 serializer/view 中。如果我们已经有了 jwt_encode_handler,也不确定手动 jwt.encode 是否是一种很好的现代方法 去做这个。您可以创建 SerializerMethodField 并在那里创建令牌:

token = serializers.SerializerMethodField()

def get_token(self, obj):
    jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
    jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

    payload = jwt_payload_handler(obj)
    token = jwt_encode_handler(payload)
    return token

然后将token字段添加到Meta.fields

Working Example