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

启用验证时JWT Token解码失败问题排查求助

问题:PHP生成的JWT在Flask中验证失败,提示"Invalid token"

问题背景

PHP生成登录后的JWT Token,登录跳转至success.php后,点击链接访问Flask路由/hi时返回{"error": "Invalid token"}。关闭签名验证(options={"verify_signature": False})可正常运行,但此方式存在安全风险,需定位根本原因。

Flask验证代码

from flask import Flask, request, jsonify
import jwt

app = Flask(__name__)
secret_key = "portal_key"

@app.route('/hi')
def hi():
    token = request.cookies.get('access_token')
    print(f"Token received: {token}")

    if not token:
        return jsonify({"error": "Unauthorized access"}), 401
    
    try:
        data = jwt.decode(token, algorithms='HS256', verify=True, key=secret_key)
        print(f"Decoded data: {data}")
        
        username = data['data']['username']
        print(username)

        if not username:
            return jsonify({"error": "Username not found in token"}), 400
        return jsonify({"message": f"Hello, {username}!"})
    
    except jwt.ExpiredSignatureError:
        return jsonify({"error": "Token expired"}), 401
    except jwt.InvalidTokenError:
        return jsonify({"error": "Invalid token"}), 401
    
if __name__ == "__main__":
    app.run(debug=True)

相关信息

  • 收到的access_token:
    eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJsb2NhbGhvc3QiLCJhdWQiOiJsb2NhbGhvc3QiLCJpYXQiOjE3MzA4MDE5OTAsImV4cCI6MTczMDgwNTU5MCwiZGF0YSI6eyJ1c2VyX2lkIjoiMjQiLCJyb2xlIjoiQWRtaW4iLCJ1c2VybmFtZSI6InNoYW5qaW5nIn19.9q4IZMuZ1SlsOqdMmoJ8XW1mynLclbRn_FfHMP4110U
    
  • 解码后的Token数据:
    {
      "iss": "localhost",
      "aud": "localhost",
      "iat": 1730801990,
      "exp": 1730805590,
      "data": {
        "user_id": "24",
        "role": "Admin",
        "username": "bob"
      }
    }
    

排查与解决方案

1. 密钥一致性检查

最常见的原因是PHP生成Token时使用的密钥与Flask的secret_key不一致:

  • 确认PHP代码中用于签名JWT的密钥是否和Flask的"portal_key"完全相同,包括大小写、空格、特殊字符(比如是否有前后空格未处理)。
  • 可将密钥和Token输入到JWT验证工具(本地离线工具即可),查看签名是否验证通过。

2. 算法匹配验证

确保PHP生成JWT时使用的是HS256算法:

  • 检查PHP代码中的JWT生成逻辑,比如使用firebase/php-jwt库时,是否明确指定HS256作为签名算法:
    // PHP示例参考代码
    use Firebase\JWT\JWT;
    
    $payload = [
        // 自定义Claims内容
    ];
    $jwt = JWT::encode($payload, $secret_key, 'HS256');
    

3. Token完整性检查

验证Token在传输过程中是否被篡改或截断:

  • 查看Flask日志中打印的Token received是否和生成的Token完全一致,是否存在多余的空格、转义字符(如\n、\r)。
  • 复制收到的Token到验证工具,确认Header、Payload、Signature三个部分都能正常解码,没有损坏。

4. Claims验证排查

Flask的jwt.decode默认会验证部分Claims(如iss、aud),如果PHP生成的Claims与Flask的验证逻辑不匹配,也会触发InvalidTokenError:

  • 可临时关闭特定Claims的验证来测试:
    data = jwt.decode(
        token,
        key=secret_key,
        algorithms='HS256',
        options={"verify_iss": False, "verify_aud": False}
    )
    
    如果验证通过,说明是Claims不匹配问题,需调整PHP生成的Claims或Flask的验证规则。

5. Base64编码格式检查

确保PHP生成的JWT使用URL安全的Base64编码:

  • JWT的三个部分必须使用URL安全的Base64编码(替换+为-,/为_,去掉末尾的=),如果PHP生成的编码不符合标准,会导致验证失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 16:07:32