Blog
从一个 Vue 3 集成页看 SSO、权限校验与第三方系统跳转设计
拆解一个轻量级 Vue 3 集成页如何串联统一登录、权限校验、第三方用户映射和安全跳转。
在一些企业系统中,前端页面并不一定承载完整业务功能,而是承担“集成桥”的角色:接收用户入口、完成统一身份认证、校验业务权限,然后把用户安全地送到目标系统。
本文结合一个 Vue 3 项目的技术结构,梳理这类集成页的常见设计方式、实现路径和需要注意的安全边界。
相关阅读 SSO 单点登录入门:从概念到前端回调流程 先理解 code、回调地址、token、会话和权限校验,再看本文的 Vue 集成页设计。项目定位
这个前端应用是一个轻量级单页应用,主要目标不是构建完整后台,而是串联几个外部系统:
- 统一登录系统
- 用户订阅或权限校验系统
- 第三方目标服务
- 本地状态与跳转控制
用户实际看到的界面很少,主要是“登录中”“身份校验中”“安全退出中”等过渡页。真正的复杂度集中在认证流程、接口调用、跳转控制和异常处理上。
技术选型
项目采用比较典型的 Vue 3 前端栈:
| 类型 | 技术 |
|---|---|
| 前端框架 | Vue 3 |
| 语言 | TypeScript |
| 构建工具 | Vite |
| 路由 | Vue Router |
| 状态管理 | Pinia |
| UI 组件 | Element Plus |
| HTTP 客户端 | Axios |
| 部署方式 | Docker + Nginx |
这个组合适合快速实现一个稳定、可维护的集成入口。Vite 负责开发和构建,Vue Router 管理登录回调和退出页,Pinia 存储短期用户状态,Axios 封装不同后端服务的调用。
页面结构
应用通常可以拆成三个核心页面:
| 页面 | 作用 |
|---|---|
| 首页入口 | 判断是否已有用户信息,没有则跳转统一登录 |
| 登录回调页 | 处理登录 code,换取用户信息并校验权限 |
| 退出页 | 清理本地状态并跳回业务入口 |
这种设计的好处是职责清晰:
- 首页只关心“用户是否可以进入目标系统”。
- 登录回调页只关心“用户身份和权限是否有效”。
- 退出页只关心“状态清理和返回入口”。
核心流程
flowchart TD
entry["用户访问入口页"] --> state{"是否已有用户状态?"}
state -->|已有状态| targetUser["查询或创建目标系统用户"]
state -->|没有状态| login["跳转统一登录"]
login --> callback["登录完成后回调前端"]
callback --> exchange["使用 code 换取用户信息"]
exchange --> permission{"调用权限或订阅校验接口"}
permission -->|无权限| error["提示错误并返回业务入口"]
permission -->|有权限| save["写入临时用户状态"]
error --> entry
save --> targetUser
targetUser --> link["获取目标系统跳转链接"]
link --> redirect["重定向到目标系统"]
关键实现点
1. 登录入口只做跳转编排
入口页不应该承载太多业务逻辑。它只需要判断当前是否有临时用户状态:
- 没有状态:拼接统一登录地址并跳转。
- 有状态:继续调用目标系统相关接口。
这样可以避免入口页变成“大杂烩”,也让登录回调和业务跳转各自独立。
2. 登录回调页负责身份闭环
登录回调页一般会从 URL 中读取一次性 code,然后调用后端接口换取用户信息。
一个更完整的回调流程通常包括:
- 检查 code 是否存在。
- 使用 code 获取登录用户信息。
- 提取用户唯一标识。
- 调用权限或订阅系统做二次校验。
- 校验成功后写入临时状态。
- 跳回入口页继续后续目标系统跳转。
这个页面要特别注意异常处理。比如 code 为空、接口失败、用户未订阅、用户 ID 缺失,都应该给出明确提示,并跳回可控入口。
3. 第三方服务调用最好通过后端中转
有些第三方接口需要签名、密钥或 client secret。如果这些信息放在前端,即使使用环境变量,也会进入最终构建产物,被浏览器用户看到。
更推荐的结构是:
flowchart LR
browser["浏览器"] --> backend["自有后端"]
backend --> thirdParty["第三方服务"]
前端只负责调用自有后端,真实密钥、签名算法、第三方 token 获取都放在服务端。这样可以降低密钥泄漏风险,也方便后端统一做审计、限流和错误处理。
4. 区分全局请求与特殊请求
项目中常见的全局 Axios 封装会做这些事情:
- 注入 Authorization
- 统一处理业务 code
- 统一处理 401、403
- 统一弹出错误提示
但并不是所有接口都适合走同一个拦截器。例如某些外部接口成功码不是 0,或者 Authorization 规则与内部接口不同,就应该创建独立 Axios 实例,避免全局拦截器误伤。
5. 状态管理要明确生命周期
登录集成页中的用户状态往往只是“跳转过程中的临时状态”。如果使用 Pinia 这类前端状态管理,需要明确:
- 是否需要刷新后仍然保留?
- 是否需要持久化到 localStorage?
- 退出时清理哪些 key?
- 是否可能影响同域下其他应用?
如果只是一次性跳转流程,内存态可能就够了。如果流程中存在刷新、跨页面或长时间等待,就应该考虑更稳妥的服务端 session 或一次性 token。
部署方式
这类项目很适合用多阶段 Docker 构建:
- Node 阶段安装依赖并执行生产构建。
- Nginx 阶段托管静态资源。
- Nginx 配置 history fallback,支持前端路由刷新。
- 对外部接口做代理,规避浏览器 CORS 问题。
需要注意的是,代理并不等于安全边界。如果代理只是把浏览器请求原样转发到第三方,前端仍然可能暴露关键参数。真正敏感的签名和凭证仍然应该放到后端。
安全检查清单
上线前建议检查:
- 前端构建产物中是否包含真实密钥。
- 是否把 client secret、AK/SK 等敏感信息放进了前端环境变量。
- 是否存在硬编码生产地址。
- 是否有过宽的本地存储清理逻辑。
- 第三方接口是否应该由后端中转。
- 依赖审计是否存在高危漏洞。
- 登录失败、权限不足、订阅过期等异常路径是否可控。
- 跳转 URL 是否可信,是否需要白名单校验。
总结
SSO 集成页看起来只是几个过渡页面,但它连接了身份、权限、第三方系统和用户跳转,属于安全边界比较敏感的位置。
实现这类项目时,前端应该专注于流程编排和用户反馈;涉及密钥、签名、第三方 token、权限判断的核心逻辑,最好下沉到后端。这样既能保持前端代码简洁,也能让系统在生产环境中更安全、更可控。