thinkphp中用firebase/php-jwt实现jwt登录,核心是签发时设uid/iat/exp/iss/aud等必要字段并签名,校验时严格验证签名、过期及算法;不依赖session,适合api与前后端分离场景。

ThinkPHP 中用 firebase/php-jwt 实现 JWT 登录,核心就两件事:签发 token 时塞进必要字段并签名,校验时严格验证签名和时间戳等关键声明。它不依赖 session,天然适合 API 接口和前后端分离场景。
安装与基础配置
先通过 Composer 安装官方推荐版本:
composer require firebase/php-jwt:^5.0
确保 PHP 版本 ≥ 8.0(TP6/TP8 均兼容)。密钥不要硬编码在代码里,应统一放在配置文件中,例如 config/jwt.php:
'secret' => env('JWT_SECRET', 'your_strong_random_string_here')-
'exp' => 3600(单位秒,建议 1–2 小时) -
'iss' => 'https://api.yourdomain.com'(签发者,用于校验) -
'aud' => 'web-app'(受众,可选但推荐)
生成 token 的关键字段和写法
签发时 payload 至少包含以下字段,缺一可能引发校验失败或安全风险:
-
uid:业务用户 ID(避免直接暴露数据库自增主键,可用加密 ID 或 UUID) -
iat:用time()记录当前时间戳 -
exp:设为time() + config('jwt.exp'),强制过期 -
iss和aud:解码时会参与比对,必须与JWT::decode()第三个参数中的白名单一致
示例代码:
$payload = [ 'uid' => $user['id'], 'username' => $user['username'], 'iat' => time(), 'exp' => time() + config('jwt.exp'), 'iss' => config('jwt.iss'), 'aud' => config('jwt.aud') ];<br>$token = JWT::encode($payload, config('jwt.secret'), 'HS256');
校验 token 的完整流程
校验不是只调一次 decode() 就完事,需捕获全部异常并设置容错时间窗口:
- 提前设置
JWT::$leeway = 60,解决服务器间时钟偏差问题 - 必须传入算法白名单数组,如
['HS256'],防止算法混淆攻击 - 捕获四类异常:
SignatureInvalidException(签名错)、ExpiredException(过期)、BeforeValidException(未生效)、DomainException(头/载荷格式非法) - 解码后得到的是对象,转数组用
(array) $decoded或json_decode(json_encode($decoded), true)
中间件中典型用法:
$token = $this->request->header('authorization');<br>if (strpos($token, 'Bearer ') === 0) { $token = trim(substr($token, 7)); }<br>try { $decoded = JWT::decode($token, new Key(config('jwt.secret'), 'HS256'));<br> $this->request = $this->request->withAttr('uid', $decoded->uid);<br>} catch (...) { return json(['code'=>401, 'msg'=>'Unauthorized']); }
安全注意事项
JWT 不是加密容器,而是带签名的结构化声明:
- payload 所有内容前端可 Base64URL 解码查看,禁止放入密码、手机号、身份证号等敏感信息
- 密钥强度要足够,推荐用
random_bytes(32)生成并存环境变量 - 不要省略
exp,也不要用超长有效期(如 30 天) - 签发时若用
nbf(not before),务必确保校验逻辑同步支持 - 生产环境禁用
none算法,始终显式指定且白名单校验
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











