当前位置: 首页 > news >正文

前端单点登录

前端实现单点登录(SSO)

单点登录(Single Sign-On,简称 SSO)是一种认证机制,允许用户在多个系统之间只需登录一次,就可以访问所有相关系统,而不需要重复输入账号和密码。它的目标是提升用户体验,同时简化认证流程。


单点登录的基本原理

单点登录的核心思想是:用户登录后,认证信息会在多个系统之间共享,用户只需登录一次,就可以访问所有系统。

通常,单点登录的实现依赖于一个统一认证中心,它负责管理用户的登录状态和认证信息。前端的主要任务是与认证中心交互,并在多个系统之间共享登录状态。

单点登录的工作流程

  1. 用户访问系统 A
    用户打开系统 A 的页面,前端检查用户是否已经登录。如果没有登录,前端会将用户重定向到认证中心。
  2. 用户登录认证中心
    用户在认证中心输入账号和密码,认证中心验证用户信息。如果验证成功,认证中心会生成一个令牌(Token)或票据(Ticket),并将其返回给前端。
  3. 前端保存令牌并访问系统 A
    前端拿到令牌后,将其保存(通常存储在 cookielocalStorage 中),并携带令牌向系统 A 发起请求。系统 A 会向认证中心验证令牌的有效性,验证通过后允许用户访问。
  4. 用户访问系统 B
    用户从系统 A 跳转到系统 B,前端会检查用户的登录状态。如果发现用户已经登录(令牌有效),则直接允许访问系统 B;如果没有登录,则重定向到认证中心进行登录。

前端实现单点登录的关键点

1. 统一认证中心

单点登录的核心是认证中心,前端需要与认证中心交互。认证中心通常提供以下功能:

  • 登录接口:用户输入账号密码后,认证中心返回令牌。
  • 验证接口:系统 A 和系统 B 可以向认证中心验证令牌的有效性。
  • 刷新接口:令牌过期后,前端可以通过认证中心刷新令牌。

2. 令牌的存储与传递

令牌是用户登录状态的凭证,前端需要妥善保存令牌,并在请求时携带令牌。常见的存储方式包括:

  • cookie:将令牌存储在浏览器的 cookie 中,设置为 httpOnlysecure,可以提高安全性。
  • localStorage:将令牌存储在 localStorage 中,适合单页面应用(SPA)。

3. 跨域问题

在单点登录中,认证中心和各个系统可能运行在不同的域名下(比如 auth.example.comsystemA.example.com)。前端需要处理跨域问题,常见的解决方法包括:

  • CORS:后端开启跨域资源共享(Cross-Origin Resource Sharing),允许前端跨域访问。
  • iframe + postMessage:通过嵌套 iframe 和消息传递实现跨域通信。

实现单点登录的流程

以下是一个简单的单点登录实现流程:

1. 检查登录状态

当用户访问系统 A 时,前端会检查用户是否已经登录。如果没有登录,则重定向到认证中心。

function checkLogin() {const token = localStorage.getItem('userToken');if (!token) {// 如果没有令牌,重定向到认证中心window.location.href = 'https://auth.example.com/login?redirect=' + encodeURIComponent(window.location.href);} else {// 如果有令牌,验证令牌是否有效validateToken(token);}
}async function validateToken(token) {const response = await fetch('https://auth.example.com/validate', {method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify({ token }),});if (response.ok) {console.log('Token is valid');} else {// 如果令牌无效,重定向到认证中心window.location.href = 'https://auth.example.com/login?redirect=' + encodeURIComponent(window.location.href);}
}

2. 登录认证中心

用户在认证中心输入账号和密码,认证中心验证成功后返回令牌。

async function login(username, password) {const response = await fetch('https://auth.example.com/login', {method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify({ username, password }),});if (response.ok) {const data = await response.json();localStorage.setItem('userToken', data.token); // 保存令牌window.location.href = data.redirectUrl; // 跳转到原始页面} else {console.error('Login failed');}
}

3. 令牌验证与共享

当用户从系统 A 跳转到系统 B 时,系统 B 的前端会检查令牌,并向认证中心验证令牌的有效性。

function checkLoginForSystemB() {const token = localStorage.getItem('userToken');if (!token) {// 如果没有令牌,重定向到认证中心window.location.href = 'https://auth.example.com/login?redirect=' + encodeURIComponent(window.location.href);} else {// 验证令牌validateToken(token);}
}

跨域单点登录的解决方案

如果认证中心和系统 A/B 运行在不同的域名下,前端需要处理跨域问题。以下是两种常见的解决方案:

1. 使用 CORS

后端开启跨域资源共享,允许前端跨域访问认证中心的接口。

// 后端设置 CORS
app.use((req, res, next) => {res.header('Access-Control-Allow-Origin', '*');res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');next();
});

2. 使用 iframe + postMessage

通过嵌套 iframe 和消息传递实现跨域通信。

// 在认证中心页面中
window.addEventListener('message', (event) => {if (event.origin === 'https://systemA.example.com') {const token = 'userTokenFromAuthCenter';event.source.postMessage({ token }, event.origin);}
});// 在系统 A 页面中
const iframe = document.createElement('iframe');
iframe.src = 'https://auth.example.com';
document.body.appendChild(iframe);window.addEventListener('message', (event) => {if (event.origin === 'https://auth.example.com') {const { token } = event.data;localStorage.setItem('userToken', token);}
});

总结

单点登录的实现需要前端与认证中心紧密配合,主要包括以下步骤:

  1. 检查用户登录状态。
  2. 重定向到认证中心进行登录。
  3. 保存令牌并验证令牌的有效性。
  4. 处理跨域问题,确保令牌可以在多个系统之间共享。

相关文章:

  • 【Linux笔记】——线程同步信号量与环形队列生产者消费者模型的实现(PV操作)
  • BigemapPro蒙版使用技巧:精准导出地图范围
  • 2025年AI搜索引擎发展洞察:技术革新与市场变革
  • 代码随想录算法训练营 Day52 图论Ⅲ 岛屿问题Ⅱ 面积 孤岛 水流 造岛
  • 基于AutoDL市场下的Pycharm远程控制
  • window 显示驱动开发-GDI 硬件加速
  • 驱动开发硬核特训 · Day 31:理解 I2C 子系统的驱动模型与实例剖析
  • 每日Prompt:双重曝光
  • 软考中级软件设计师——计算机网络 IP地址与子网掩码相关题型
  • 亚远景-汽车软件开发的“升级之路”:ASPICE各等级说明
  • 汽车充电过程中--各个电压的关系(DeepSeek)
  • Vue+eElement ui el-input输入框 type=number 输入无效。赋值输入框也不显示(问题已解决)
  • 新能源汽车焊接智能节气阀
  • 46 python pandas
  • 2025 年暑假 LBE 大空间市场火爆程度预测:技术驱动与消费升级下的增长引擎
  • JavaSenderMail发送邮件(QQ及OFFICE365)
  • 指令烧录ORIN NANO操作系统
  • 地图收费,企业成本骤增,有哪些替代方案可破局?
  • Brave 连接 Websocket 失败
  • 第8天-Python趣味绘图:用Turtle库开启绘画编程之旅
  • 新华时评:网络平台“开盲盒式”扣费,“钱小”事大
  • 迪拜工业城2025年初表现强劲,有望迎来投资增长新高
  • 为俄乌一日三通电话,这里成“关键战场”?
  • 上海市政府党组赴全面从严治党警示教育基地参观学习,推进作风建设走深走实
  • 凤阳文旅局长回应鼓楼瓦片脱落事件:楼宇是否属于文物?施工经费用在何处?
  • 上海合作组织减贫和可持续发展论坛开幕,沈跃跃宣读习近平主席贺信