前端单点登录实现方案全解析
一、基于Cookie的单点登录方案
1、原理
- 在同一个顶级域名下,多个子域可以共享Cookie,公司有a.example.com
、b.example.com
等多个子域,当用户在其中一个子域(如a.example.com
)登录成功后,服务器会在响应中设置一个包含用户登录信息(如用户ID、登录状态等)的Cookie,并且设置其域名为.example.com
(顶级域名),这样,当用户访问其他子域(如b.example.com
)时,浏览器会自动带上这个Cookie。
- 前端在每个子域的页面加载时,可以通过JavaScript检查这个共享Cookie的存在与否来判断用户是否已经登录,如果Cookie存在且有效,就可以根据其中的用户信息显示已登录状态,例如显示用户头像、用户名等相关信息。
图片来源于网络,如有侵权联系删除
2、实现步骤
- 登录子域的设置:在登录成功的子域(如a.example.com
)中,后端服务器在登录成功的响应中设置Cookie,在Node.js中使用express
框架的话,可以这样设置:
```javascript
const express = require('express');
const app = express();
app.post('/login', (req, res) => {
const user = { id: 1, name: 'John' };
res.cookie('user_info', JSON.stringify(user), { domain: '.example.com', path: '/' });
res.send('Login successful');
});
```
- 其他子域的验证:在其他子域(如b.example.com
)的前端页面中,可以通过以下JavaScript代码检查Cookie:
```javascript
function checkLogin() {
const cookieValue = document.cookie.match('(^|;)\\s*user_info\\s*=\\s*([^;]+)');
if (cookieValue) {
const userInfo = JSON.parse(cookieValue[2]);
// 根据用户信息显示已登录状态
document.getElementById('user - avatar').src = 'avatar - url';
document.getElementById('user - name').textContent = userInfo.name;
} else {
// 显示未登录状态,如显示登录按钮
}
}
window.onload = checkLogin;
```
3、优缺点
- 优点:实现相对简单,不需要复杂的前端架构调整,对现有系统的侵入性较小,并且在同一个顶级域名下,Cookie的共享机制天然适合子域间的单点登录。
- 缺点:存在安全风险,因为Cookie可以被客户端修改,虽然可以通过加密等手段增强安全性,但仍然需要谨慎处理,如果涉及到跨顶级域名的单点登录,这种方案就无法直接使用。
二、基于Token的单点登录方案
1、原理
- 当用户在某个应用(如应用A)登录成功后,服务器会生成一个包含用户身份信息的Token(通常是一个加密的字符串,如JWT - JSON Web Token),这个Token会被返回给前端应用A,前端会将这个Token存储起来,一般存储在localStorage
或者sessionStorage
中。
- 当用户访问其他相关应用(如应用B)时,前端会将存储的Token发送给应用B的服务器,应用B的服务器会对这个Token进行验证,验证通过则认为用户已经登录,验证过程包括检查Token的签名是否正确(以确保Token没有被篡改)、检查Token是否过期等。
2、实现步骤
- 登录应用的Token获取:在登录成功的应用(如应用A)中,后端返回Token给前端,前端接收到Token后,存储起来,使用JavaScript在Vue.js应用中:
```javascript
async function login() {
const response = await axios.post('/login', { username: 'user', password: 'pass' });
const token = response.data.token;
图片来源于网络,如有侵权联系删除
localStorage.setItem('auth_token', token);
}
```
- 其他应用的Token验证:在其他应用(如应用B)的前端,当需要访问受保护资源时,会从存储中取出Token并添加到请求头中发送给后端。
```javascript
async function getData() {
const token = localStorage.getItem('auth_token');
const response = await axios.get('/protected - data', {
headers: {
'Authorization':Bearer ${token}
}
});
return response.data;
}
```
- 后端验证:在应用B的后端(如使用Node.js和express - jwt
中间件),可以这样验证Token:
```javascript
const express = require('express');
const app = express();
const jwt = require('express - jwt');
const secret = 'your - secret - key';
app.get('/protected - data', jwt({ secret: secret }), (req, res) => {
res.send('Protected data');
});
```
3、优缺点
- 优点:安全性相对较高,因为Token可以进行加密签名,并且可以设置过期时间等属性,它适合于跨域的单点登录场景,只要各个应用能够验证Token即可。
- 缺点:前端需要妥善处理Token的存储和传输安全,如果存储在localStorage
,存在XSS(跨站脚本攻击)风险,可能导致Token被盗取,并且Token的验证逻辑需要在每个应用的后端进行正确配置,增加了一定的复杂性。
三、使用单点登录框架(如OAuth、CAS等)的方案
1、原理
- 以OAuth为例,它是一个开放标准的授权框架,在单点登录场景中,有一个授权服务器(如公司内部的身份认证中心),当用户想要访问某个受保护的资源(如应用A中的特定功能)时,应用A会将用户重定向到授权服务器进行登录(如果用户尚未登录)。
- 授权服务器验证用户身份后,会生成一个授权码(在OAuth 2.0中),并将用户重定向回应用A,应用A再使用这个授权码向授权服务器换取访问令牌(Access Token),然后就可以使用这个访问令牌访问受保护资源,当用户访问其他应用(如应用B)时,应用B也可以遵循相同的流程从授权服务器获取访问令牌来验证用户身份。
2、实现步骤(以OAuth 2.0为例)
- 注册应用:在授权服务器上注册应用A和应用B,注册过程中会获取到客户端ID(Client ID)和客户端密钥(Client Secret)等信息。
- 应用A的登录流程:
- 重定向到授权服务器:在应用A的前端,当用户点击登录按钮或者访问需要授权的资源时,前端会构造一个重定向URL到授权服务器,
```javascript
const clientId = 'your - client - id';
const redirectUri = 'https://app - a.example.com/callback';
图片来源于网络,如有侵权联系删除
const authUrl =https://auth - server.example.com/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code
;
window.location.href = authUrl;
```
- 回调处理:在授权服务器验证用户身份并将用户重定向回应用A的回调URL(https://app - a.example.com/callback
)后,前端需要处理这个回调,在回调中,会从URL中获取授权码,然后使用这个授权码向授权服务器换取访问令牌。
```javascript
function handleCallback() {
const code = new URLSearchParams(window.location.search).get('code');
const clientId = 'your - client - id';
const clientSecret = 'your - client - secret';
const redirectUri = 'https://app - a.example.com/callback';
const tokenUrl = 'https://auth - server.example.com/oauth/token';
const data = {
client_id: clientId,
client_secret: clientSecret,
code: code,
redirect_uri: redirectUri,
grant_type: 'authorization_code'
};
axios.post(tokenUrl, data).then(response => {
const accessToken = response.data.access_token;
// 存储访问令牌并进行后续操作
localStorage.setItem('access_token', accessToken);
});
}
window.onload = handleCallback;
```
- 应用B的登录流程:应用B的登录流程与应用A类似,也是先重定向到授权服务器,然后在回调中获取访问令牌,不过,应用B会使用自己的客户端ID和客户端密钥。
3、优缺点
- 优点:
- 标准化程度高,OAuth等框架被广泛应用,有成熟的解决方案和社区支持。
- 安全性较好,因为涉及到多轮验证和授权过程,包括授权码的使用等机制,降低了安全风险。
- 适合多平台、多应用的单点登录场景,无论是Web应用、移动应用还是桌面应用都可以集成。
- 缺点:
- 实现相对复杂,需要对OAuth等框架有深入的理解,并且需要正确配置授权服务器和各个应用的相关参数。
- 对网络依赖较大,因为每次登录或获取令牌都需要与授权服务器进行交互,如果授权服务器出现故障或者网络延迟较大,可能会影响用户体验。
在实际的前端单点登录实现中,需要根据项目的具体需求,如应用的架构、安全要求、是否跨域等因素来选择合适的单点登录方案。
评论列表