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

如何从过期JWT Token中提取payload获取user_id以重发账户激活邮件

解决JWT过期时提取user_id的方案

你可以通过关闭JWT的过期时间校验(保留签名校验,防止伪造token)来从过期的有效token中提取payload内容,以下是两种适配你现有代码的实现方式:


方法1:使用PyJWT原生参数关闭过期校验

在jwt.ExpiredSignatureError捕获块中,重新调用jwt.decode时添加options={"verify_exp": False}参数,仅跳过过期时间校验,仍然验证token签名合法性,就能拿到payload里的user_id,修改后代码如下:

@api_view(['POST'])
def ConfirmEmailView(request):
    try:
        activation_token = request.data['activation_token']
        payload = jwt.decode(activation_token,settings.SECRET_KEY,  algorithms=['HS256'])
        user = User.objects.get(id = payload['user_id'])
        if user.is_confirmed:
            return Response('Already verified!', status=status.HTTP_200_OK)  
        user.is_confirmed = True
        user.save()
        return Response(status=status.HTTP_202_ACCEPTED)

    except jwt.ExpiredSignatureError as identifier:
        # 仅跳过过期时间校验,仍验证签名合法性,防止伪造token
        payload = jwt.decode(
            activation_token,
            settings.SECRET_KEY,
            algorithms=['HS256'],
            options={"verify_exp": False}
        )
        user_id = payload['user_id']
        # 此处调用你封装的激活邮件发送逻辑,给对应用户重发邮件
        # 注意添加发送频率限制,避免被恶意刷接口
        return Response("激活链接已过期,新的激活邮件已发送至您的邮箱", status=status.HTTP_403_FORBIDDEN)

    except Exception as e:
        print(e)
        return Response(status=status.HTTP_400_BAD_REQUEST)

方法2:使用djangorestframework-simplejwt内置工具解析(更适配你的token生成逻辑)

因为你生成激活token用的是simplejwt的RefreshToken,也可以直接用simplejwt的内置能力解析,后续如果调整simplejwt的签名算法、密钥等配置不需要额外修改解码参数:

from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework_simplejwt.exceptions import TokenError

@api_view(['POST'])
def ConfirmEmailView(request):
    try:
        activation_token = request.data['activation_token']
        payload = jwt.decode(activation_token,settings.SECRET_KEY,  algorithms=['HS256'])
        user = User.objects.get(id = payload['user_id'])
        if user.is_confirmed:
            return Response('Already verified!', status=status.HTTP_200_OK)  
        user.is_confirmed = True
        user.save()
        return Response(status=status.HTTP_202_ACCEPTED)

    except jwt.ExpiredSignatureError as identifier:
        try:
            # verify=False仅跳过过期校验,仍会验证签名合法性
            token = RefreshToken(activation_token, verify=False)
            user_id = token['user_id']
            # 此处调用重发邮件逻辑
        except TokenError:
            # token签名无效,属于伪造请求,直接返回错误
            return Response("无效的激活链接", status=status.HTTP_400_BAD_REQUEST)
        return Response("激活链接已过期,新的激活邮件已发送至您的邮箱", status=status.HTTP_403_FORBIDDEN)

    except Exception as e:
        print(e)
        return Response(status=status.HTTP_400_BAD_REQUEST)

注意事项

  • 无论用哪种方法,都必须保留签名校验,不能直接拆分JWT字符串裸取payload,否则会被伪造的恶意请求滥用,导致你的邮件发送接口被刷
  • 重发激活邮件前建议添加频率限制,比如同一用户1分钟内只能请求重发1次,避免对用户造成邮箱轰炸,也减少你的邮件服务成本

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 16:15:09