一句话定位:单点登录(SSO)不是“同一个账号登录多个系统”,而是“一次认证,全体系信任”。 在 Java + Vue 前后端分离架构下,它的本质是把“登录”从各个业务系统中抽离出来,交给一个独立的认证中心统一管理,并通过标准化的令牌传递机制,实现跨系统、跨域的身份互认。
一、什么是 SSO?——为什么需要它
1.1 传统登录的三大痛点
在多系统企业中,用户每天可能要切换 OA、CRM、财务等多个系统,每进入一个系统都要重新输入账号密码 。这背后的本质问题是:
| 用户体验差 | 每个系统独立登录,账号密码重复输入 | 各系统独立维护 Session |
| 开发维护难 | 每个系统都要做登录模块,密码策略变更需全量修改 | 认证逻辑分散 |
| 安全风险高 | 用户密码重复使用,一处泄露处处危险 | 缺乏统一的认证管理 |
1.2 SSO 的解决方案
SSO 通过引入一个独立的认证中心(IdP),将用户的登录态从“各系统分别记住”变成“认证中心统一管理”,让“一次登录,全网通行”成为现实 。
二、SSO 的核心架构与关键角色
2.1 三大核心角色
| 身份提供商(IdP) | Identity Provider | 负责用户登录验证、颁发令牌、管理全局会话 | 独立的 SSO 认证服务(Java Spring Boot 开发) |
| 服务提供商(SP) | Service Provider | 各业务子系统,依赖 IdP 完成认证 | 各个 Vue + Java 业务系统 |
| 用户 | User | 终端使用者 | 浏览器端用户 |
2.2 核心组件职责拆分
| 认证中心(SSO Server) | 用户登录、颁发 Token、验证 Token 有效性、管理全局会话 | Spring Boot + Spring Security + JWT + Redis |
| 业务系统(SSO Client) | 拦截未登录请求、向认证中心校验 Token、建立本地会话 | Java:Spring Security 过滤器 / 拦截器;Vue:路由守卫 + Axios 拦截器 |
| 令牌存储 | 存储 Token 与用户信息的映射关系,支持分布式 Session | Redis(分布式缓存) |
三、SSO 的运行流程
3.1 首次登录:完整认证流程
3.2 访问第二个系统:免登录流程
| 1 | 用户访问业务系统B | — |
| 2 | 系统B检测到无本地Token | 重定向到认证中心 |
| 3 | 认证中心检测到全局会话存在 | 通过 Cookie 中的 SessionId 判断 |
| 4 | 直接颁发Token给系统B | 无需再次输入密码 |
| 5 | 系统B建立本地会话 | 用户免登录访问成功 |
核心机制:用户浏览器在 IdP 域名下保存了全局会话 Cookie,这是“一次登录、多系统互通”的关键凭证 。
3.3 退出登录
| 全局登出 | 用户登出一个系统,所有系统同步登出 | 销毁IdP全局会话 + 通知所有SP销毁局部会话 |
| 局部登出 | 仅登出当前系统 | 仅销毁该SP的本地会话 |
四、SSO 在 Java + Vue 项目中的技术实现全景
4.1 前后端分离架构下的 SSO 设计
在 Java + Vue 前后端分离架构下,SSO 的实现需要额外处理跨域问题。核心思路是:前端统一管理 Token,后端统一校验 Token 。
| 前端(Vue) | 路由守卫 | 拦截未登录请求,重定向到认证中心 |
| Axios 拦截器 | 自动在请求头中携带 Token | |
| Token 存储 | 存储在 localStorage 或 Cookie 中 | |
| 后端(Java) | 过滤器 / 拦截器 | 拦截请求,校验 Token 有效性 |
| Token 解析 | 从 Token 中提取用户信息 | |
| 用户信息注入 | 将用户信息注入到当前线程上下文 |
4.2 前端关键实现
javascript
// Vue 路由守卫:检查登录状态
router.beforeEach(async (to, from, next) => {
const token = localStorage.getItem('sso_token')
if (!token) {
// 重定向到 SSO 认证中心
window.location.href = `${SSO_SERVER_URL}/login?redirect=${encodeURIComponent(window.location.href)}`
return
}
// 验证 token 有效性(调用后端接口)
const isValid = await verifyToken(token)
if (!isValid) {
window.location.href = `${SSO_SERVER_URL}/login?redirect=${encodeURIComponent(window.location.href)}`
return
}
next()
})
// Axios 拦截器:自动携带 Token
axios.interceptors.request.use(config => {
const token = localStorage.getItem('sso_token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
4.3 后端关键实现
java
// Spring Boot 过滤器:拦截并校验 Token
@Component
public class SsoAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) {
String token = request.getHeader("Authorization");
if (token == null) {
// 重定向到 SSO 认证中心
response.sendRedirect(ssoServerUrl + "/login");
return;
}
// 向认证中心校验 Token(或本地 JWT 验签)
UserInfo user = ssoClient.verifyToken(token);
if (user == null) {
response.sendRedirect(ssoServerUrl + "/login");
return;
}
// 将用户信息注入当前线程上下文
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities())
);
filterChain.doFilter(request, response);
}
}
五、SSO 的主流实现方案对比
| 基于 Cookie+Session | IdP 域名下保存全局 Session Cookie | 实现简单,易于控制登出 | 跨域限制严格,扩展性差 | 同一主域下的企业内部系统 |
| 基于 JWT(轻量级 SSO) | IdP 签发 JWT,SP 本地验签 | 无状态,跨域友好,实现简单 | 无法主动销毁,Token 泄露风险 | 跨域场景,移动端,微服务 |
| 基于 OAuth 2.0 + OIDC | 标准协议,支持授权码流程 | 行业标准,支持多种授权模式,安全性高 | 实现复杂,需维护多套端点 | 需要对接第三方应用,开放平台 |
| 基于 CAS 协议 | 票据(Ticket)交换机制 | 成熟稳定,专为 SSO 设计 | 需部署独立 CAS Server | 高校、政府等传统企业级应用 |
5.1 JWT vs OAuth 2.0:关键区别
| 核心用途 | 身份认证(Authentication) | 授权(Authorization)+ 身份认证 |
| Token 验证 | SP 本地验签(无状态) | SP 需向 IdP 验证(或有状态) |
| 安全性 | 需妥善管理私钥 | 支持授权码 + PKCE 等增强安全机制 |
| 适用场景 | 内部系统,轻量级应用 | 对接第三方应用,开放平台 |
六、SSO 落地的关键技术要点
6.1 跨域问题处理
在前后端分离架构中,前端和后端可能部署在不同域名下。处理方式 :
| Cookie 携带 Token | 设置 withCredentials: true,后端配置 CORS | 同主域或已配置 Cookie 跨域共享 |
| Authorization Header | 前端将 Token 存入 localStorage,通过请求头传递 | 完全跨域场景,最通用 |
| URL 参数传递 | Token 通过 URL 参数传递 | 仅限首次授权回调场景 |
6.2 令牌存储策略
| localStorage | 容量大,持久化 | 存在 XSS 攻击风险 | 不适合存储敏感 Token,建议配合 HttpOnly Cookie |
| HttpOnly Cookie | 防止 XSS 读取 | 受域名限制,存在 CSRF 风险 | 配合 SameSite=Strict 和 CSRF Token |
| Session Storage | 关闭标签页即清除 | 跨标签页不共享 | 适合临时性 Token |
6.3 分布式 Session 管理
在分布式部署场景下,必须解决 Session 共享问题。推荐使用 Redis 作为分布式 Session 存储 :
java
// 使用 Redis 存储用户会话信息
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public void saveSession(String token, UserInfo user) {
redisTemplate.opsForValue().set(
"sso:session:" + token,
user,
30, TimeUnit.MINUTES
);
}
public UserInfo getSession(String token) {
return (UserInfo) redisTemplate.opsForValue()
.get("sso:session:" + token);
}
七、SSO 实战全景架构图
text
┌─────────────────────────────────────────────────────────────────┐
│ 用户(浏览器) │
└─────────────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 前端层(Vue) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 系统A前端 │ │ 系统B前端 │ │ 系统C前端 │ │
│ │ 路由守卫拦截 │ │ 路由守卫拦截 │ │ 路由守卫拦截 │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
└─────────┼────────────────┼────────────────┼───────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ 后端层(Java) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 系统A后端 │ │ 系统B后端 │ │ 系统C后端 │ │
│ │Token校验过滤器│ │Token校验过滤器│ │Token校验过滤器│ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
└─────────┼────────────────┼────────────────┼───────────────────┘
│ │ │
└────────────────┼────────────────┘
▼
┌─────────────────────────────────────────────────────────────────┐
│ SSO 认证中心(Java) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 登录认证接口 │ │ Token签发 │ │ Token校验 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Redis(分布式Session存储) │
│ Token → 用户信息 映射存储 / 黑名单管理 │
└─────────────────────────────────────────────────────────────────┘
八、总结
| SSO 的本质 | 将“登录”从各业务系统中抽离,交给独立的认证中心统一管理,实现“一次认证,全体系信任” |
| 核心组件 | 身份提供商(IdP)+ 服务提供商(SP)+ 令牌存储(Redis) |
| 主流方案 | Cookie+Session(同域)、JWT(跨域)、OAuth2+OIDC(标准化)、CAS(传统企业) |
| 前后端分离架构要点 | 前端路由守卫拦截 + Axios 自动携带 Token;后端过滤器统一校验 Token |
| 关键设计决策 | JWT 无状态适合跨域,需配合黑名单处理登出;OAuth2 标准协议适合对接第三方 |
| 安全建议 | HttpOnly Cookie 存储 Token 防止 XSS,结合 CORS 和 CSRF Token 加固防护 |
九、按技术栈场景
| 同一主域下的多应用 | 同一公司下的多个业务系统,共享二级域名(如 app1.example.com、app2.example.com) | Cookie+Session(同域SSO),实现最简单 |
| 完全跨域的多应用 | 不同域名下的多个系统(如 oa.company.com、crm.company.com) | JWT + OAuth2/OIDC(跨域SSO) |
| 前后端分离架构 | Vue/React 前端 + Java/Go 后端,前端部署在静态站点,后端独立服务 | JWT + Authorization Header |
| 移动端 + PC 端 | 同一套用户体系,同时支撑 Web 端和 APP 端 | JWT + Refresh Token |




