ThinkPHP中JWT过期时间配置有5种方式:一、生成时手动设置exp时间戳;二、通过config/jwt.php统一管理时长;三、用Redis缓存jti实现动态吊销;四、设leeway容差应对时钟偏差;五、结合Refresh Token实现无感续期。

如果您在ThinkPHP项目中使用JWT进行身份认证,但发现令牌未按预期时间失效,则可能是由于exp声明未正确写入载荷或验证逻辑未启用时间检查。以下是配置JWT过期时间的具体方法:
一、在Token生成时显式设置exp字段
JWT的过期机制依赖于载荷(payload)中标准声明exp的UNIX时间戳值,该值必须为整数且大于当前时间戳。ThinkPHP自身不内置JWT实现,需借助第三方库(如firebase/php-jwt),因此需在构造payload数组时手动计算并注入exp。
1、在Token类的生成方法中,使用time()或Carbon::now()->addMinutes()计算过期时间戳。
2、将计算结果以键值对形式加入payload数组,键名为exp,值为整型时间戳。
立即学习“PHP免费学习笔记(深入)”;
3、调用JWT::encode()时传入该payload,确保签名过程包含exp字段。
4、验证端调用JWT::decode()时,库会自动比对当前时间与exp值,若超时则抛出ExpiredException异常。
二、通过配置文件统一管理过期时长
将过期时间从硬编码解耦至配置文件,便于多环境差异化设置,并避免业务代码中重复计算。ThinkPHP支持在config/jwt.php中定义参数,供Token类动态读取。
1、在config目录下新建jwt.php配置文件,写入'access_expire' => 3600(单位:秒)。
2、在Token生成逻辑中,使用Config::get('jwt.access_expire')获取数值。
3、执行$payload['exp'] = time() + Config::get('jwt.access_expire')。
4、确保配置文件被正确加载,例如在服务提供者中调用Config::load()。
三、使用Redis缓存扩展实现动态过期控制
标准JWT的exp为只读声明,无法在签发后修改。若需支持管理员强制使某用户令牌提前失效,须引入外部状态存储。Redis可作为轻量级吊销中心,配合exp做双重校验。
1、生成JWT后,以jti(JWT ID)为key、当前时间戳为value,写入Redis并设置相同TTL。
2、在中间件验证流程中,先执行JWT::decode()完成基础时间校验。
3、再根据解析出的jti查询Redis,若key不存在或已过期,则拒绝访问。
4、登出操作触发DEL命令删除对应jti的Redis记录,实现即时失效。
四、适配分布式部署的时钟偏差容错
当ThinkPHP应用部署于多台服务器且系统时间未严格同步时,可能出现token在A服务器校验通过、在B服务器因本地时间偏快而判定过期的情况。需引入容忍窗口缓解该问题。
1、在JWT::decode()调用时,传入第三个参数$leeway(容差秒数),例如new Key($secret, 'HS256', 30)。
2、确保所有服务器启用NTP服务并指向同一时间源,如pool.ntp.org。
3、避免使用microtime(true)等高精度时间函数生成exp,统一采用time()保证整秒粒度。
4、在日志中记录decode时的服务器本地时间与payload中iat/exp值,用于偏差排查。
五、结合Refresh Token实现无感续期
单一短时效access token会导致频繁登录,影响体验。通过分离access token与refresh token职责,可在保障安全前提下延长有效会话。
1、登录成功后,同时生成两个token:access_token(exp=1800秒)、refresh_token(exp=604800秒)。
2、将refresh_token存入HttpOnly Secure Cookie,禁止JavaScript访问;access_token存于内存或localStorage。
3、前端拦截401响应,携带refresh_token请求/refresh接口换取新access_token。
4、/refresh接口验证refresh_token有效性后,签发新access_token并返回,不刷新refresh_token本身或重置其过期时间。



















