You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为每个用户配置独立的djangorestframework-simplejwt SIGNING_KEY

为每个用户配置独立JWT签名密钥(djangorestframework-simplejwt)

要实现每个用户用独立的jwt_secret作为JWT签名密钥,并支持通过更新该字段强制用户下线,需要重写simplejwt的核心类,步骤如下:

1. 自定义Token生成序列化器

重写TokenObtainPairSerializer,在生成Token时使用当前用户的jwt_secret作为签名密钥:

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer

class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        # 将用户的jwt_secret转为字符串作为签名密钥
        token.signing_key = str(user.jwt_secret)
        return token

2. 自定义JWT认证类

默认的JWTAuthentication会使用全局签名密钥验证Token,需要重写它,确保验证时使用对应用户的jwt_secret,这样当用户的密钥更新后,旧Token会验证失败:

from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework_simplejwt.exceptions import InvalidToken

class CustomJWTAuthentication(JWTAuthentication):
    def get_user(self, validated_token):
        user = super().get_user(validated_token)
        # 用用户当前的jwt_secret重新验证Token签名
        try:
            validated_token.verify(str(user.jwt_secret))
        except Exception:
            raise InvalidToken("Token无效或用户已被强制下线")
        return user

3. 更新项目配置

在settings.py中替换默认的序列化器和认证类:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        # 替换为自定义的认证类
        'your_app.authentication.CustomJWTAuthentication',
    ),
}

SIMPLE_JWT = {
    # 替换为自定义的Token生成序列化器
    'TOKEN_OBTAIN_SERIALIZER': 'your_app.serializers.CustomTokenObtainPairSerializer',
}

4. 实现强制下线逻辑

当需要让用户从所有终端下线时,只需更新该用户的jwt_secret字段即可:

import uuid
from django.contrib.auth import get_user_model

User = get_user_model()
user = User.objects.get(id=target_user_id)
user.jwt_secret = uuid.uuid4()
user.save()

更新后,用户之前生成的所有Token(包括Access和Refresh Token)都会因签名不匹配而失效,必须重新登录获取新Token。


内容的提问来源于stack exchange,提问作者Santhosh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 20:42:49