不透明 Token

从「查数据库」开始

我的 App 上线后,Web 和移动端都要登录。我面临一个选择:登录成功之后,后续请求怎么证明「这是同一个已登录用户」?

最朴素的做法,就是登录成功后生成一个随机字符串,把它和用户、会话、过期时间一起存到服务端,然后把字符串交给客户端:

token = random(256bit)     // 例如 9f3a...c2e1

客户端每次请求带上这个 token,服务端拿它查存储,确认身份。

这种 token 本身没有任何业务含义,所以叫不透明 Token(Opaque Token)。

优点:好撤销,好控制

不透明 Token 最大的优点,是它的一切都掌握在服务端手里:

  • 随时可撤销:在存储里把状态一改,token 立即失效。
  • 完全可控:可以记录设备、过期时间、风险等级,想加什么字段都行。
  • 不怕泄露含义:token 本身就是个随机数,没有可解析的信息,猜不出来。

缺点:每次都要查

代价也很直接:每次请求都要查一次服务端存储(数据库或 Redis)。请求量一大,这个查询就会成为压力点。

所以通常会把会话状态放进 Redis:查询快、带过期时间,天然适合。

什么时候选它

不透明 Token 非常适合这些场景:

  • 对撤销要求严格(金融、账号安全)——改个状态就能让凭证失效。
  • 单服务或少数服务——查询成本可控。
  • 不需要跨服务离线验证。

它的反例是:当你有几十个微服务、每个请求都要验证身份时,每次都查 Redis 既增加延迟,又让所有服务强依赖会话存储。

一个直觉

把不透明 Token 想成更安全的 Session ID:它不存用户信息,只存一个「去服务端查」的钥匙。安全上,因为内容不可解析、状态可撤销,它常常比「自包含」的方案更稳妥——代价是每次查询。

下一节看另一种思路:把身份信息直接写进 Token 的 JWT。

发现内容有问题?

告诉我们哪里需要改进。