如何在Django Rest Framework简单JWT中使用访问和刷新令牌返回自定义数据来标识用户?

时间:2018-11-26 12:06:43

标签: django-rest-framework django-rest-framework-jwt

在Django中,超级用户可以根据其角色添加更多用户。我使用带有DRF的简单JWT进行身份验证。但是,仅通过查看访问和刷新令牌就无法检测用户的类型。

这是我的settings.py文件

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAuthenticated',),
    'DEFAULT_AUTHENTICATION_CLASSES': ('rest_framework_simplejwt.authentication.JWTAuthentication',),


}

urls.py

from django.contrib import admin
from django.urls import path, include
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView


urlpatterns = [

    path('admin/', admin.site.urls),
    path('', include('Manage_Merchants.urls')),

    path('api-auth', include('rest_framework.urls')),
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),


]

当我通过邮递员点击127.0.0.1:8000/api/token/时,它会要求输入用户名和密码。当我输入用户名和密码时,它会生成一个刷新和访问令牌。 Generate JWT with DRF using Postman

那么我如何识别为超级用户或其他用户创建的超级用户生成的令牌?如何通过字典和访问令牌和刷新令牌传递更多的价值来识别用户类型?

3 个答案:

答案 0 :(得分:9)

在版本djangorestframework-simplejwt==4.4.0中,它是方法validate而不是to_representation,意思是:

在您的serializer.py中,您需要覆盖TokenObtainPairSerializer以便在响应中包含要发送的所有数据

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer


class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    def validate(self, attrs):
        # The default result (access/refresh tokens)
        data = super(CustomTokenObtainPairSerializer, self).validate(attrs)
        # Custom data you want to include
        data.update({'user': self.user.username})
        data.update({'id': self.user.id})
        # and everything else you want to send in the response
        return data

现在,在您的views.py中,您需要覆盖TokenObtainPairView才能将其与新的序列化器配对。

from .serializers import CustomTokenObtainPairSerializer


class CustomTokenObtainPairView(TokenObtainPairView):
    # Replace the serializer with your custom
    serializer_class = CustomTokenObtainPairSerializer

现在将其映射到您的url.py

from rest_framework_simplejwt.views import TokenRefreshView, TokenVerifyView
from . import views

urlpatterns = [
    # This one now has the custom view mapped with the custom serializer that includes the desired data
    path('token/', views.CustomTokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
    path('token/verify/', TokenVerifyView.as_view(), name='token_verify')
]

答案 1 :(得分:1)

就像kumar所说,您应该重写TokenObtainPairView。让我更深入地了解它:

在您的核心应用程序views.py中创建一个新的classView,或者如果您想要一个更简洁的代码,则可以创建一个名为jwt_token_patched的新应用程序,并在其中创建一个views.py文件。现在,向其添加以下代码:

class TokenObtainPairPatchedView(TokenObtainPairView):
    """
    Takes a set of user credentials and returns an access and refresh JSON web
    token pair to prove the authentication of those credentials.
    """
    serializer_class = serializers.TokenObtainPairPatchedSerializer

    token_obtain_pair = TokenObtainPairView.as_view()

现在为序列化程序添加以下内容:

class TokenObtainPairPatchedSerializer(TokenObtainPairSerializer):
     def to_representation(self, instance):
         r = super(TokenObtainPairPatchedSerializer, self).to_representation(instance)
         r.update({'user': self.user.username})
         return r

当序列化程序以json格式返回数据时,将调用to_representation()方法,因此您可以在其中添加任何所需的内容。记住,我只是将用户名放在用户字段值中,您可以在其中添加所需的用户的任何项目值。

还为此创建一个URL,从现在开始使用该方法获取令牌。 如有问题,请随时提问。希望它是有用的:)

答案 2 :(得分:1)

对于自定义刷新令牌,您可以做的最好的事情是覆盖如下所示的“TokenRefreshSerializer”。但是,如果您想从模型中获取任何字段,我们必须对令牌进行解码以获取用户的 UUID。这可以使用 token_backend

来完成

注意:请确保您使用的是“rest_framework_simplejwt”而不是“djangorestframework-jwt”,因为它已被弃用

from rest_framework_simplejwt.serializers import TokenRefreshSerializer
from rest_framework_simplejwt.state import token_backend

class CustomTokenRefreshSerializer(TokenRefreshSerializer):
    def validate(self, attrs):
        data = super(CustomTokenRefreshSerializer, self).validate(attrs)
        decoded_payload = token_backend.decode(data['access'], verify=True)
        user_uid=decoded_payload['user_id']
        # add filter query
        data.update({'custom_field': 'custom_data')})
        return data

然后使用这个序列化程序,如下所示,“CustomTokenRefreshView”继承了“TokenRefreshView”

from rest_framework_simplejwt.views import TokenRefreshView
class CustomTokenRefreshView(TokenRefreshView):
    """
    Custom Refresh token View
    """
    serializer_class = CustomTokenRefreshSerializer

并将其添加到网址中

path('api/token/refresh/', CustomTokenRefreshView.as_view(), name='token_refresh'),