纯 PHP 项目应选 firebase/php-jwt,因其轻量、可控且兼容 PHP 8.1;lexik/jwt-authentication-bundle 仅适用于 Symfony/Laravel,不兼容原生 PHP。

JWT扩展选 firebase/php-jwt 还是 lexik/jwt-authentication-bundle?
PHP 8.1 环境下,纯 PHP 项目直接用 firebase/php-jwt 更轻量、可控;Laravel 项目才考虑 lexik/jwt-authentication-bundle(它底层也调 firebase/php-jwt)。别被“Bundle”误导——它不兼容原生 PHP,装了反而报 Class "Symfony\Component\HttpKernel\Bundle\Bundle" not found。
安装命令就是:
composer require firebase/php-jwt:^6.10注意必须是 v6.10+,因为低版本不支持 PHP 8.1 的
DateTimeImmutable 构造方式,否则签发 token 时会抛 TypeError: DateTimeImmutable::__construct(): Argument #1 ($datetime) must be of type string。
JWT::encode() 和 JWT::decode() 怎么传参数才不踩坑?
PHP 8.1 要求密钥类型严格:不能传空字符串、不能传 null、不能用弱类型数组当 payload。常见错误是写成 JWT::encode($payload, ''),结果报 InvalidArgumentException: Key may not be empty。
正确做法:
立即学习“PHP免费学习笔记(深入)”;
- 密钥必须是字符串,建议从环境变量读:
$_ENV['JWT_SECRET'] ?? 'your-32-byte-secret-here' - Payload 必须是关联数组,且键名避开
iat、exp、nbf等保留字段(除非你真要控制时间逻辑) - 签发时显式指定算法:
JWT::encode($payload, $secret, 'HS256'),别依赖默认值——PHP 8.1 下省略第三个参数可能触发弃用警告 - 解码必须 try/catch:
JWT::decode($token, $secret, ['HS256']),失败会抛DomainException或SignatureInvalidException,不捕获就崩
如何安全地把 JWT 放进 HTTP 请求头而不被 XSS 或 CSRF 利用?
别把 token 存 localStorage —— XSS 一打一个准;也别自动塞 Cookie(尤其没设 HttpOnly)—— CSRF 可能重放。
推荐组合:
- 登录成功后,后端返回 token(不要带 refresh token),前端存入
httpOnly+Secure+SameSite=Strict的 Cookie(如jwt_token) - 后续请求由浏览器自动带上该 Cookie,后端用
$_COOKIE['jwt_token']读取并验证 - 如果必须用 Bearer Header(比如 API 调试或跨域场景),确保前端只从内存变量(如
const token = response.data.token)取值,绝不从 DOM 或 URL 解析 token
额外提醒:PHP 8.1 默认开启 session.cookie_httponly=1,但你要检查 php.ini 里 session.cookie_samesite 是否设为 Strict 或 Lax,否则 Cookie 可能在 POST 请求中丢失。
为什么 exp 时间到了却没报错,或者提前失效?
JWT 的过期判断依赖系统时间,PHP 8.1 不再容忍时间漂移。如果你的服务器时间不准(差几秒),JWT::decode() 就可能误判 exp 或 nbf。
解决办法只有两个:
- 强制校验前同步时间:在 decode 前加
date_default_timezone_set('UTC');,并确保服务器运行chrony或ntpd - 给
exp留缓冲:比如用户要 1 小时 token,实际设'exp' => time() + 3660,多给 1 分钟容错
另一个隐藏坑:JWT::decode() 默认不做 exp 检查,除非你传了第四个参数(验证选项数组)。必须显式写成:
JWT::decode($token, $secret, ['HS256'], ['leeway' => 60])其中
leeway 是允许的时间误差秒数,PHP 8.1 下这个参数不能省。



















