在分布式系统、移动应用及Web服务的开发过程中,用户认证是保障系统安全的第一道防线。传统的单令牌认证方案往往陷入了安全性与用户体验的两难困境:长期有效令牌容易被窃取,短期有效令牌则需要用户频繁登录。
引言
当我们构建分布式系统、移动应用或Web服务时,可靠的用户认证机制是守护系统安全的首要关卡。传统的单令牌认证面临着安全与体验的经典矛盾——赋予令牌过长有效期会增加泄露后被长期滥用的风险,而过短的有效期又会迫使用户反复登录,体验糟糕。而基于双令牌的Token机制(access token + refresh token)巧妙地对令牌职责进行了精细化分工,完美地破解了这一两难局面。
传统单令牌
图片
登录认证:令牌的生成与存储
用户登录时,客户端将账号密码发送至服务器的认证中心进行校验。当认证通过后,系统会生成一个访问令牌(token)。随后,服务器将这个令牌返回给客户端,由客户端将其保存在本地,可以选择存储在内存或本地持久化存储中。
资源访问:令牌的验证与响应
登录成功后,每当客户端请求受保护的资源时,都会在请求中附带这个令牌。服务器接收请求后,会首先验证该令牌的有效性,包括检查其是否过期、签名是否合法等。若令牌验证有效,服务器直接返回请求的资源数据;如果令牌无效或已过期,则向客户端返回401未授权错误。
令牌过期与重新认证
客户端收到401响应后,意味着原有的令牌已失效,此时需要重新走一遍完整的登录认证流程。待用户再次输入账号密码并获得新的单次令牌后,才能继续访问受保护的资源。
劣势
安全风险高:若令牌被设置为长期有效,一旦不慎泄露,攻击者便可在很长一段时间内非法访问系统,造成持续性的安全威胁。
体验差:若为了安全将令牌设为短期有效,用户则会频繁遇到会话过期的提示,不得不反复重新登录,操作流程被打断,用户体验非常不流畅。
双Token机制
图片
登录认证:令牌的生成与存储
用户提交账号密码后,请求被发送到服务器的认证中心。在验证凭证通过后,系统会同时生成两个令牌:短期的访问令牌和长期的刷新令牌。服务器将这对令牌返回给客户端。客户端通常将短期的access token存储在内存或本地存储中,用于日常请求;而长期的refresh token则建议存储在标记为HttpOnly的Cookie里,这种做法能有效降低令牌被恶意脚本窃取的风险。
资源访问:令牌的验证与响应
成功登录后,客户端每次访问受保护的API资源时,只需在请求头中携带短期的access token。服务器端接收到请求后,会优先校验这个access token的有效性。如果令牌有效且未过期,服务器便直接返回请求的资源。倘若access token无效或已过期,服务器则返回401未授权状态码。
令牌续期:无感刷新与重新登录
当客户端从API请求中得到401响应后,会自动触发基于refresh token的无感刷新流程:客户端会向认证中心发起一个专门的令牌刷新请求,并附上长期的refresh token。如果这个refresh token依然有效,认证中心会立即颁发一组全新的access token,客户端收到后更新本地存储,并自动用新令牌重试刚才失败的资源请求,整个过程对用户完全透明。如果refresh token也过期了,认证中心会返回失效提示,客户端则需要清空所有本地存储的令牌,并跳转至登录页面,要求用户重新输入账号密码进行身份验证。
优势:体验与安全的双重保障
安全性: 短期有效的access token确保了访问安全,即便不幸泄露,攻击者能够利用的窗口期也极短。
流畅体验: 长期有效的refresh token保障了用户会话的持续性,用户无需频繁手动登录即可实现会话的静默续期,体验流畅。
职责分离: 双令牌各司其职,实现了安全防护与用户体验的完美平衡与兼顾。
