外观
单点登录是怎么实现的?
用户在认证中心登录一次,多个应用信任这张票,不必各自再收一次密码。前端负责跳转和保存本应用的会话,认证中心负责签发和校验。前端不能自己宣布「已经登录」。
原理
常见流程:
- 应用发现没有会话,把用户带到认证中心,并带上自己的回调地址。
- 认证中心登录成功后,重定向回应用,并附上一次性授权码。
- 应用的服务器用授权码向认证中心换令牌,再给浏览器建立自己的会话。
授权码不要留在浏览器里当长期凭证。回调地址必须事先登记,否则会被人换成攻击者的地址把授权码带走。
同父域的多个子站可以把会话 Cookie 写在父域。这只在你控制这些子域时成立,而且要收紧 Path、Secure 和 SameSite。完全不同的主域不能共享这块 Cookie,必须走上面的跳转。
退出要通知认证中心,并尽量让其他应用的会话失效。只清当前站点的 localStorage,别的标签页和别的应用还是登录的。
追问
和 OAuth、JWT 的关系?
OAuth 描述授权码怎么发、怎么换。JWT 可以是换回来的令牌格式。单点登录是「一次认证、多个应用」的产品流程,可以用这套协议实现。见 JWT。
前端为什么不直接向认证中心换令牌?
换令牌需要客户端密钥,密钥不能放进页面。这一步放在应用自己的服务器上。公开客户端有另外的约束(PKCE),面试里说明密钥不进浏览器即可。
易错点
- 把密码或长期令牌放进 URL。授权码可以出现在回调里,但只能用一次、寿命很短。
- 不校验回调里的
state,用户可能被带到攻击者发起的登录流程里。 - 只在一个前端项目里清登录态,就说已经单点退出。