PHP转Python实现Bearer Token生成遇401错误,求排查
问题:PHP生成的Bearer Token可用,Python复现返回401
我有一段PHP脚本,可通过用户ID和密码生成有效的Bearer Token,但用Python复现相同逻辑时,始终返回401错误。PHP脚本会将生成的JWT按.拆分后,取第2、3个元素(索引1和2)拼接输出,Python中我执行了同样的拼接操作,但问题依旧。
PHP 实现代码
#!/usr/bin/env php <?php require __DIR__ . '/app/vendor/php-jwt/JWT.php'; /* * Acquisition date are UTC dates */ date_default_timezone_set('UTC'); /* * Default values */ $days = 1; $help = "\nGenerate a resto JSON Web Token (aka rJWT) authentication token for user\n"; $help .= "\n USAGE : generateAuthToken [options] \n"; $help .= " OPTIONS:\n"; $help .= " -i [bigint] : userid (mandatory)\n"; $help .= " -d [int] : duration of token in days (default " . $days . ")\n\n"; $help .= " -p [string] : passphrase (mandatory)\n"; $options = getopt("d:i:p:h"); /* * Default values */ $days = 1; $options = getopt("i:d:p:h"); foreach ($options as $option => $value) { if ($option === "d") { $days = $value; } if ($option === "i") { $userid = $value; } if ($option === "p") { $passphrase = $value; } } $exp = time() + (86400 * $days); $splitJWT = explode('.', JWT::encode(array( 'sub' => $userid, 'iat' => time(), 'exp' => time() + (86400 * $days) ), $passphrase)); echo "$splitJWT[1].$splitJWT[2]"; ?>
Python 原实现代码
from datetime import datetime, timedelta import jwt JWT_SECRET = '<>' JWT_ALGORITHM = 'HS256' JWT_EXP_DELTA_SECONDS = 86400 ADMIN_USER_ID="<>"" payload = { 'user_id': ADMIN_USER_ID, 'exp': datetime.utcnow() + timedelta(seconds=JWT_EXP_DELTA_SECONDS) } print(payload) encoded_jwt = jwt.encode(payload, JWT_SECRET , algorithm='HS256') x = encoded_jwt.split(".") x1 = x[1] + "." + x[2] print(x1)
问题根源及修正方案
核心差异点
- Payload字段不匹配:PHP中用
sub存储用户ID,而Python用user_id,服务端验证时会无法识别用户身份,这是401的主要原因。 - 缺少
iat字段:PHP的Payload包含iat(签发时间戳),部分服务端会校验该字段的存在性。 - 时间格式差异:PHP用整数时间戳,Python用datetime对象,虽然
pyjwt能自动转换,但统一用时间戳更稳妥。
修正后的Python代码
import time import jwt JWT_SECRET = '<>' JWT_ALGORITHM = 'HS256' JWT_EXP_DELTA_SECONDS = 86400 ADMIN_USER_ID = "<>" current_timestamp = int(time.time()) payload = { 'sub': ADMIN_USER_ID, # 改为和PHP一致的sub字段 'iat': current_timestamp, # 新增签发时间字段 'exp': current_timestamp + JWT_EXP_DELTA_SECONDS # 用整数时间戳 } encoded_jwt = jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGORITHM) x = encoded_jwt.split(".") x1 = x[1] + "." + x[2] print(x1)
内容的提问来源于stack exchange,提问作者Ramkumar Ramagopalan
相关产品推荐
相关产品推荐

