
嘻道奇闻
- 文章199742
- 阅读14625734
PHP生成带过期时间的Token实现教程(附代码)
你做的登录功能是不是总被老板骂不安全?用户刚登录半小时就被盗号?八成是没给Token加"保质期"!今天咱们就用煮泡面的功夫,教你搞出带过期时间的Token,保准连黑客都直摇头!
一、为什么Token要有保质期?
想象一下你家大门钥匙永远不换,是不是慌得睡不着?Token过期时间就是给钥匙加个自动销毁程序。??三大核心作用??:
- ??降低风险??:就算被盗,有效期过了也白搭
- ??强制更新??:定期更换加密规则
- ??清理内存??:自动释放服务器存储空间
??反面教材??:
- 某社交APP的7天免登录 → 被盗号者玩成永久权限
- 某电商平台Token永不过期 → 被黑产批量倒卖
- 某政府系统用session_id当Token → 分分钟被破解
二、四种实现方式任你选
▍ 方法1:时间戳+随机数(新手村装备)
php复制$token = md5(time() . bin2hex(random_bytes(16))); $expire = time() + 7200; // 2小时后过期
??适合场景??:临时文件下载、验证码等低安全需求
▍ 方法2:数据库记录法(经典款)
php复制// 生成 $token = bin2hex(random_bytes(32)); $expires_at = date('Y-m-d H:i:s', time() + 3600); // 存数据库 $db->query("INSERT INTO tokens (token, user_id, expires_at) VALUES ('$token', 123, '$expires_at')");
??查过期技巧??:
php复制SELECT token FROM tokens WHERE expires_at > NOW()
▍ 方法3:JWT自带过期(高端玩家必备)
php复制use Firebase\JWT\JWT; $payload = [ 'user_id' => 123, 'exp' => time() + 1800 // 重点在这里! ]; $token = JWT::encode($payload, '你的密钥', 'HS256');
▍ 方法4:加密饼干法(Cookie流派)
php复制$data = [ 'user_id' => 123, 'exp' => time() + 86400 // 24小时 ]; $token = base64_encode( openssl_encrypt( json_encode($data), 'AES-256-CBC', '密钥至少32位', 0, '初始向量也要16位' ) );
三、过期时间设置的五大黄金法则
-
??长短搭配更安全??
场景 推荐时长 理由 移动端APP 7-30天 减少重复登录 后台管理系统 2-4小时 敏感操作多 支付流程 5-15分钟 资金安全 验证链接 30分钟 平衡安全与用户体验 -
??动态调整更智能??
- 用户保持活跃时自动续期
- 异地登录立即失效
- 修改密码后所有Token过期
-
??服务器时间要校准??
遇到过期的坑?检查这三处:- PHP时区设置
date_default_timezone_set('Asia/Shanghai')
- 数据库服务器的系统时间
- Nginx/Apache的时区配置
- PHP时区设置
-
??容错时间窗??
加个缓冲期,防止时间不同步:php复制
$isValid = ($token_expire_time > time() - 300); // 允许5分钟误差
-
??多端不同步处理??
手机、电脑、平板同时登录?给每个设备发独立Token!
四、代码实战:带自动续期的Token
php复制function generateToken($userId) { $secret = '你的密钥应该比银行卡密码还复杂'; $expire = 3600; // 基础有效期1小时 // 根据用户等级延长有效期 if ($user->isVIP()) { $expire = 2592000; // 30天 } $payload = [ 'iat' => time(), 'exp' => time() + $expire, 'user_id' => $userId, 'version' => '2023_token_v2' // 密钥更新时让旧Token集体失效 ]; return hash_hmac('sha256', json_encode($payload), $secret); } // 检查是否过期 function checkToken($token) { // 解密逻辑... if ($payload['exp'] < time()) { // 自动续期条件:7天内登录过且不是重要操作 if ($payload['version'] == CURRENT_TOKEN_VERSION && time() - $payload['iat'] < 604800) { return generateToken($payload['user_id']); } throw new Exception('Token已过期'); } }
五、避坑指南:血泪经验大放送
-
??千万别用客户端时间??
有次前端小哥用JavaScript生成过期时间,结果用户修改系统时间就永久有效了! -
??数据库索引要到位??
曾经因为没给expires_at字段加索引,百万级数据查询直接卡死 -
??密钥管理三不要??
- 不要写死在代码里
- 不要用Github免费搜索能找到的密钥
- 不要所有环境用同一套密钥
-
??日志记得打码??
见过有程序员把完整Token写进日志文件,结果被运维导出泄露 -
??定期清理过期Token??
用cron定时任务每天凌晨3点删过期数据:sql复制
DELETE FROM tokens WHERE expires_at < NOW()
说点得罪人的大实话
Token过期时间这玩意儿,就像汽车的刹车系统。用时间戳+随机数相当于手刹,JWT方案是ABS防抱死系统,自定义加密那是赛车级碳陶刹车盘。但甭管用啥,最重要的是——别以为自己写了个完美方案就高枕无忧!
去年我帮朋友审计代码,发现他用的加密算法组合比俄罗斯套娃还复杂,结果密钥居然用公司名字+成立年份,黑客三分钟就破解了。所以啊,安全这回事,往往不是技术不够高级,而是基础操作没做到位。
最后送大家一句话:Token的过期时间不是越长越好,也不是越短越安全。就像煮泡面,3分钟太硬,5分钟太烂,找到最适合自己业务的"黄金4分钟"才是王道!