JWT Token + Cookie SSO
一、认识
在同顶级域下实现 SSO
(单点登录) 解决方案,主要是指多个子域名(如 app.example.com
和 portal.example.com
)共享同一个身份认证状态,使得用户只需在某一个子域下登录一次,就能在所有子域下访问其他受保护的资源。
二、工作
基于 JWT Token + Cookie
实现同顶级域下 SSO
方案, 并实现 Token
无感刷新, 核心思路是通过一个统一的身份认证服务(Identity Provider
,简称 IDP
)来处理用户的身份认证,并将认证信息(Token
)存储在 Cookie
中,确保不同子域能共享该信息。主要的流程可以分为以下几个步骤:
1. 用户登录认证: 用户首先访问某个子域(如 app.example.com
),如果该用户还没有登录,系统会将用户重定向到 认证服务(IDP
),通常是一个统一的身份认证服务器。用户在 IDP
系统中进行登录(通常是通过用户名和密码),认证通过后,IDP
会基于 JWT
生成一个包含用户信息的 Access Token
和用于重新生成 Access Token
的 Refresh Token
。将 Access Token
存储在 Cookie
中, 并加上 HttpOnly
和 Secure
保护,防止 JS
获取和防止中间人攻击。将 Refresh Token
存储到 Redis
中, Refresh Token
通常会设置较长的有效期(如 7 天)。设置 Cookie Domain=.example.com
,这意味着该 Cookie
可以在 example.com
下的所有子域间共享。在同顶级域下,所有子域名共享一个主域名(如 .example.com
),因此,可以通过设置 Cookie
的 Domain
属性来让 Cookie
在多个子域间共享。以下是对 Cookie
配置的解释:
-
Secure
:确保Cookie
只能通过HTTPS
协议传输,增强安全性。 -
HttpOnly
:防止客户端JavaScript
直接访问Cookie
,从而降低XSS
攻击的风险。 -
SameSite=None
:允许跨域请求时发送Cookie
,解决跨子域的Cookie
问题。 -
Domain=.example.com
:确保Cookie
对所有子域(如app.example.com
、portal.example.com
)有效。
2. 用户后续请求验证: 用户访问 portal.example.com
或其他子域时,浏览器会自动将存储在 Cookie
中的 Access Token
发送给该子域。子域的后端服务会从请求中提取出 Access Token
,并将其发送到身份认证服务(IDP
)进行验证。如果 Access Token
有效,认证通过,用户可以继续访问资源。后端服务会将验证结果返回给前端,或者直接允许用户访问需要的资源。如果 Access Token
过期,身份认证服务(IDP
)会尝试从 Redis
获取 Refresh Token
并验证其有效性。如果 Refresh Token
有效,身份认证服务(IDP
)会尝试使用 Refresh Token
来刷新 Access Token
并返回新的 Access Token
。如果 Refresh Token
无效或过期,则返回 401
错误,要求前端重新登录。
3. 用户退出登录: 当用户退出登录时,前端应用会清除浏览器中存储的认证 Access Token
(通常是删除 Cookie
) 和身份认证服务(IDP
) Redis
中的 Refresh Token
。如果需要,IDP
还可以实现全局注销,即用户退出登录时,不仅仅是在当前子域下登出,还会在所有子域中登出(例如清除所有子域下的 Cookie
)。