【问题标题】:Adding information to JWT token body using django rest framework jwt使用 django rest framework jwt 向 JWT 令牌主体添加信息
【发布时间】:2016-08-24 14:51:08
【问题描述】:

我正在使用 django rest 框架和 djangorestframework-jwt 包来创建 JWT 令牌以进行授权。

在前端,我可以解码令牌并获取用户名、电子邮件和 user_id。但是我想检索一些额外的信息。例如,如果我能得到kind,这是我们授权模型(用户模型)上的一个字段,那将非常方便。

我当然可以单独请求通过常规 APIView 获取用户信息。但我想知道是否可以在 JWT 正文中添加一些额外的参数?

【问题讨论】:

  • 是的,你可以在 djangorestframework-jwt 中编辑 utils.py

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


【解决方案1】:

使用djangorestframework_simplejwt

  1. 在 settings.py 中指定 USER_ID_FIELD 和 ALGORITHM

    SIMPLE_JWT = {
        'USER_ID_FIELD': 'user_id',
        'ALGORITHM': 'HS512',
    }
    

假设您要向具有以下主体的 TokenObtainPairView 主体添加字段

{
    "refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTU5MDk5ODAwMSwianRpIjoiMjZhZThhYTU4YTJiNDU3M2JlMDgxNTMzMzU1ODg4ZmUiLCJ1c2VyX2lkIjoxMX0.-jUCnfpTF-RsqHnuoEgctPpHf1SfYNcYaPs8oo01RvrQBMcyhms5PfWipfYkaR0FlPHSTKncNeMxomwd4k7nyg",
    "access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTkwOTExOTAxLCJqdGkiOiI5NjZkOTFhNzEzNjg0NjMyOGUzYWU3NThiNzNiZmYxMyIsInVzZXJfaWQiOjExfQ.LiHrekmlHrM7_5187ghpIaA6mKcPCjDz4MDKPXHc4QAKVGvcJCJpCjrODCB4-pZn4Kuai5ht3YjWwYSirxpsXw"
}
  1. 添加你的 urls.py

    path('api/token/', MyTokenObtainPairView.as_view(), name='token_obtain'),
    
  2. 创建 MyTokenObtainPairView

    class MyTokenObtainPairView(TokenObtainPairView):
        serializer_class = MyTokenObtainPairSerializer`
    
  3. 创建 MyTokenObtainPairSerializer

    class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
        def validate(self, attrs):
            data = super().validate(attrs)
            refresh = self.get_token(self.user)
            data['refresh'] = str(refresh)
            data.pop('refresh', None) # remove refresh from the payload
            data['access'] = str(refresh.access_token)
    
            # Add extra responses here
            data['user'] = self.user.username
            data['kind'] = self.user.kind
            data['date'] = datetime.date.today()
            return data
    

这样,当您发布到 /api/token/ 时,您会在正文中获得类似这样的内容

{
    "access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTkwOTEwNTc0LCJqdGkiOiIwM2Q5MzA1NTZmNzk0NmFjODU1MzJlNTYzNjUwZDY0MCIsInVzZXJfaWQiOjExfQ.H0huO84qtzdbo4OkKhsW_vtNTGwInG67gum6f138h1y66EiyZ1BvxaxbfEE2oPG4pB0XjiWQrXc5PlR9C6UvfQ",
    "user": "tiago",
    "kind": "whatever_this_has"
    "date": "2020-05-31"
}

【讨论】:

  • 文档中是否提到了这一点?
  • @KrishnadasPC 我不知道
  • Martin 你是怎么找到这个的?该代码适用于我,但在其他任何地方都找不到。
  • @KrishnadasPC 它出现在我想添加到正文和声明的那一刻。另见this onethis one
【解决方案2】:

正如github issue 中所述,我通过从 DRF-JWT 继承 ObtainJSONWebToken 类来做到这一点:

from rest_framework_jwt import views as jwt_views
from .serializers import UserSerializer 

class UserLoginViewJWT(jwt_views.ObtainJSONWebToken):
    user_serializer_class = UserSerializer

    def post(self, request, *args, **kwargs):
        response =  super().post(request, *args, **kwargs)

        if response.status_code == status.HTTP_200_OK:
            user = get_user_model().objects.get(email=request.data[get_user_model().USERNAME_FIELD])
            serialized_user = self.user_serializer_class(user)
            response.data.update(serialized_user.data)
        return response

注意:上面的代码可能缺少一些导入

@jpadilla 的回复也指出

您也可以使用 JWT_RESPONSE_PAYLOAD_HANDLER 设置来执行此操作。 http://getblimp.github.io/django-rest-framework-jwt/#jwt_response_payload_handler

【讨论】:

    猜你喜欢
    • 2019-08-01
    • 2017-06-25
    • 2017-03-30
    • 2019-06-20
    • 2019-02-26
    • 2017-05-28
    • 2018-02-24
    • 2020-06-18
    • 2021-03-10
    相关资源
    最近更新 更多