Skip to content

Token 策略分析

一句话:对比Token刷新和会话独立两种策略,推荐混合方案。

注意:框架已实现Token刷新功能,可通过 useApp.php 中的 token.refresh 配置项启用。

详见:用户认证文档


两种方案对比

方案1:Token验证后生成新Token(刷新Token)

工作原理:

  • 每次Token验证成功后,自动生成新的Token
  • 客户端需要更新本地存储的Token
  • 旧Token可以立即失效或设置短暂宽限期

优点:

  • 安全性高:定期轮换Token,减少泄露风险
  • 检测异常使用:如果旧Token被使用,可以检测到异常
  • 自动续期:活跃用户无需重新登录
  • 简化管理:无需存储Token列表

缺点:

  • 客户端复杂度:需要处理Token刷新逻辑
  • 网络开销:每次验证都要生成新Token
  • 并发问题:多个请求同时验证可能导致Token冲突
  • 用户体验:如果客户端未及时更新,可能导致请求失败

方案2:会话独立Token(每个会话有独立的Token)

工作原理:

  • 每个登录会话生成唯一的Token
  • Token与session_id绑定
  • Token存储在数据库或缓存中,可以单独管理

优点:

  • 会话追踪:可以追踪每个设备的登录状态
  • 精确控制:可以单独撤销某个会话的Token
  • 多设备支持:不同设备有独立Token,互不干扰
  • 客户端简单:Token固定,无需刷新逻辑

缺点:

  • 存储开销:需要存储Token列表,数据库或缓存
  • 管理复杂:需要定期清理过期Token
  • 性能影响:每次验证需要查询存储
  • 扩展性:大量并发用户时,存储压力大

推荐方案:混合策略(会话独立加可选刷新)

结合两种方案的优点,推荐以下实现:

核心设计

  1. 会话独立Token

    • 每个登录会话生成唯一Token
    • Token与session_id强绑定
    • Token存储在内存缓存中(Redis/Memcached)或数据库
  2. 可选刷新机制

    • 配置项控制是否启用自动刷新
    • 刷新时更新过期时间,不改变Token本身
    • 支持Token续期延长有效期
  3. Token管理

    • 支持查看所有活跃Token
    • 支持撤销特定Token
    • 自动清理过期Token

实现建议

php
// 配置选项
'app.token' => [
    'enabled' => true,
    'strategy' => 'session_based', // 'session_based' | 'refresh'
    'auto_refresh' => false,        // 是否自动刷新
    'refresh_threshold' => 0.3,     // 剩余时间 < 30% 时刷新
    'store' => 'cache',              // 'cache' | 'database'
    'max_sessions' => 5,            // 每个用户最大会话数
]

方案选择建议

选择方案1(刷新Token)的场景:

  • 单设备应用(移动App)
  • 对安全性要求极高
  • 客户端可以很好地处理Token刷新
  • 用户量不大,性能不是瓶颈

选择方案2(会话独立)的场景:

  • 多设备/多浏览器支持
  • 需要精确的会话管理
  • 需要支持"踢出设备"功能
  • 高并发场景,需要快速验证

选择混合方案(推荐)的场景:

  • 需要平衡安全性和用户体验
  • 支持多设备登录
  • 需要灵活的Token管理
  • 生产环境应用

安全性对比

特性刷新Token会话独立混合方案
泄露后风险低(定期轮换)中(可撤销)低(可撤销加轮换)
会话劫持防护
多设备支持
实现复杂度
性能开销

最终建议

推荐使用混合方案,原因:

  1. 灵活性:可以根据业务需求调整策略
  2. 安全性:结合两种方案的优点
  3. 可扩展性:未来可以轻松添加新功能
  4. 用户体验:支持多设备,不会频繁要求重新登录

实现优先级:

  1. 先实现会话独立Token基础功能
  2. 再添加可选刷新机制增强功能
  3. 最后添加Token管理功能

Released under the MIT License.