(链接地址: https://leapcell.io/?lc_t=d_jsauth)
在前端项目开发过程中,用户认证通常采用四种主要方式:Session、JWT、SSO和OAuth 2。
那么,这四种方法各自的优缺点是什么?今天我们就来比较比较它们!
经典基于会话的认证什么是基于会话的身份验证?
基于会话的认证方式是一种常被用于前端和后端系统的用户认证方法。
它主要依靠服务器来创建和管理用户会话。
会话的工作原理
会话认证过程分为六个步骤。
- 用户登录:用户在登录界面输入其凭据(例如用户名和密码)。这些凭据从前端发送到后端服务器进行验证。
- 创建会话:验证用户信息后,后端服务器创建会话,通常包括一个唯一的会话ID,并将其存储在服务器上。
- 返回会话ID:服务器将包含会话ID的cookie回传给浏览器。此cookie存储在用户的浏览器中,并会随后续请求自动发送。
- 存储会话ID:浏览器保存cookie,并在每次发送给服务器的请求中自动包含该cookie。这使服务器能够识别用户的会话并进行身份验证。
- 会话验证:服务器查找会话ID并验证相关的会话信息以确定用户的身份。它还可以使用会话数据进行权限检查和访问控制。
- 会话超时和管理:服务器可以设置会话超时时间,并定期清理过期的会话。当用户注销或会话超时时,服务器会删除或使该会话失效。
从上述过程来看,我们可以看到在基于会话的认证机制中,前端无需主动介入。关键操作——在浏览器和服务器之间进行处理。
利弊.
优势
- 简单易用:管理会话和用户认证对于开发者来说相对比较容易。
- 良好的兼容:大多数浏览器支持 cookies,可以自动发送和接收。
缺点
- 较差的扩展性:在分布式系统中,多个服务器可能需要共享会话存储,增加了系统的复杂性。
- 需要 HTTPS:如果 cookie 被窃取,可能导致会话被劫持。因此,使用 HTTPS 来保证数据传输的安全,并采取其他安全措施(例如,为 cookie 设置
HttpOnly
和Secure
属性)。
代码示例
这里有一个使用 Express 实现会话授权的例子:
const express = require('express');
const session = require('express-session');
const app = express();
// 配置并使用 express-session 中间件
app.use(
session({
secret: 'your-secret-key', // 用于签署会话 ID cookie 的密钥,以确保会话的安全
resave: false, // 是否在每次请求时都保存会话,即使会话未更改
saveUninitialized: true, // 是否保存未初始化的会话数据
cookie: {
secure: true, // 是否仅通过 HTTPS 发送 cookie(需要支持 HTTPS)
maxAge: 24 * 60 * 60 * 1000, // cookie 过期时间(设置为 24 小时)
},
})
);
// 登录路由处理程序
app.post('/login', (req, res) => {
// 验证用户(假设用户已验证)
const user = { id: 123 }; // 示例用户 ID
req.session.userId = user.id; // 将用户 ID 存储在会话中
res.send('登录成功.');
});
app.get('/dashboard', (req, res) => {
if (req.session.userId) {
// 如果会话中包含用户 ID,则表示用户已登录
res.send('仪表盘内容...');
} else {
// 如果会话中未找到用户 ID,则表示用户未登录
res.send('请先登录...');
}
});
app.listen(3000, () => {
console.log('服务器正在监听端口 3000...');
});
点击切换到全屏,点击退出全屏模式,fullscreen 全屏
认证使用 JSON Web Token (JWT)你知道什么是JWT认证吗?
JWT认证目前是最常用的一种认证方法。
服务器返回一个token,用来表示用户身份。在每次请求时,都会将这个token添加到请求头中来进行用户身份验证。
由于HTTP请求是无状态,这种方法也常被称为无状态认证。
JWT 是怎么工作的:
- 用户登录:用户在登录页面输入其凭据(如用户名和密码),并将这些凭据发送到后端服务器进行验证。
- 生成JWT:在验证用户凭据后,后端服务器生成一个JWT。该令牌通常包含基础用户信息(如用户ID)和元数据(如过期时间)。
- 返回JWT:服务器将生成的JWT通常通过JSON响应返回给前端。
- 存储JWT:前端将JWT存储在客户端,通常存储在
localStorage
中。在某些特殊情况下,JWT可能会存储在cookies中,但这会带来诸如跨站脚本攻击(XSS)和跨站请求伪造(CSRF)等安全风险。 - 发起API请求:当发起API请求时,前端在
Authorization
头中附加JWT令牌(格式:Bearer <token>
),并将其发送到服务器。 - 验证JWT:收到请求后,服务器提取JWT,验证其有效性并检查签名和过期时间。如果有效并且,服务器处理请求并返回相应的资源或数据。
- 响应请求:服务器处理请求并返回响应,前端可以据此使用响应。
优缺点
优势
- 无状态 : JWT 本身包含所有必要信息,因此服务器无需保存会话状态,简化了扩展性和负载均衡的过程。
- 跨域支持 : JWT 适用于跨域请求(如 API 和前端分离的情况)。
缺点
- 安全问题:JWT的安全性依赖于密钥保护和令牌的有效期管理;如果JWT被盗,可能会带来安全威胁。
代码示例:
这里是一个使用Express进行JWT认证的示例:
const express = require('express');
const jwt = require('jsonwebtoken');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
const secretKey = 'your-secret-key'; // 用于签署和验证 JWT 的密钥字符串
// 用于生成 JWT 的登录接口
app.post('/login', (req, res) => {
const { username, password } = req.body;
// 假设用户有效
const user = { id: 1, username: 'user' }; // 示例用户信息
const token = jwt.sign(user, secretKey, { expiresIn: '24h' }); // 生成用于登录的 JWT
res.json({ token }); // 返回登录成功的 JWT
});
// 受保护的接口
app.get('/dashboard', (req, res) => {
const token = req.headers['authorization']?.split(' ')[1];
if (!token) {
return res.status(401).send('未提供 token');
}
jwt.verify(token, secretKey, (err, decoded) => {
if (err) {
return res.status(401).send('无效的 JWT');
}
res.send('仪表盘详情');
});
});
app.listen(3000, () => {
console.log('服务器正在端口 3000 监听...');
});
全屏模式 退出全屏
单签通(SSO)认证单点登录(SSO)验证
单点登录(SSO)常用于 “套件式” 应用程序。通过一个 中央登录系统 ,用户可以一次登录并访问多个应用程序,而无需重复认证。
单点登录(SSO)是怎么工作的
- 用户访问应用:用户尝试访问需要身份验证的应用(称为服务提供方(SP))。
- 被重定向至身份提供商(IdP):由于用户未登录,应用将其重定向到SSO 身份提供商(IdP)(通常称为单点登录中心(SSO登录中心))。单点登录中心处理用户的身份验证。
- 用户登录:用户在单点登录中心输入其凭据。如果他们已经登录(例如,登录到公司内部的SSO系统),则可以跳过这一步。
- SSO 令牌生成:经过身份验证后,身份提供商生成一个SSO 令牌(例如,OAuth令牌或SAML断言),并将其重定向回原始应用,并附带令牌。
- 令牌验证:应用(服务提供方)接收令牌并将其发送到SSO 身份提供商进行验证。身份提供商验证令牌,然后返回用户的身份数据。
- 用户获得访问权限:经过成功验证后,应用根据用户的身份信息授予访问权限。用户现在可以访问应用的受保护内容。
- 访问其他应用程序:如果用户访问使用相同单点登录中心(SSO登录中心)的其他应用程序,他们将被重定向到该登录中心。由于他们已经登录,单点登录中心会自动验证其身份,然后将其重定向回目标应用,从而实现无缝登录。
利弊:
优点
- 简化用户体验:用户只需登录一次即可访问多个应用程序,从而避免了重复登录的繁琐。
- 集中管理:管理员可以集中管理用户身份和访问权限,提高效率和安全性。
- 增强安全性:减少了密码泄露的风险,用户只需要记住一个密码。还可以强制使用更强的身份验证机制(例如:多因素认证(MFA))。
不足
- 单点失效:如果登录中心(SSO身份提供商)出现问题,所有依赖它的应用可能会受到影响。
- 复杂实现方式:部署和维护SSO解决方案可能很复杂,需要正确的安全配置,并确保系统间的互操作性。
常见的单点登录实现技术
安全断言标记语言 (SAML)
- 一种基于 XML 的标准,用于身份提供方(IDP)和服务提供方(SP)之间交换认证与授权数据。
- 常用于企业环境中。
OAuth 2.0 与 OpenID Connect
- OAuth 2.0 是一个授权框架,用于让第三方访问用户资源。
- OpenID Connect 建立在 OAuth 2.0 之上,增加了一个用于用户身份验证的身份层。
- 经常在 Web 和移动应用 中使用。
CAS(中央认证系统)
- 一个开源的单点登录 (SSO) 解决方案,让使用者只需一次登录,就能访问多个网络应用。
OAuth 2.0身份验证是什么?
OAuth 2.0 是一个用于授权第三方应用访问用户资源的标准授权协议,比如下面的例子。
- 脸书登录
- Discord 登入
- 二维码登录
OAuth 2.0 主要设计用于授权,而不是认证,但它常常与认证结合使用,让用户登录。
OAuth 2.0 是怎么运作的
OAuth 2.0 相当复杂,所以在真正理解它的流程之前,我们需要先搞清楚一些关键概念。
OAuth 2.0 的关键概念
- 资源所有者:通常指的是拥有受保护资源(比如个人数据或文件)的用户。
- 资源服务器:托管受保护资源并且保证只有授权用户才能访问的服务器。
- 客户端:希望访问受保护资源的软件或服务。客户端必须获得资源所有者的授权。
- 授权服务器:负责验证资源所有者身份并向客户端发放访问权限的服务器。它发放访问令牌,让客户端能够访问资源服务器。
OAuth 2.0 工作流
- 用户授予授权:当用户与客户端应用互动时,应用程序请求访问用户的资源的授权。用户将被重定向到授权服务器。
- 获取授权码:如果用户同意,授权服务器生成一个授权码并通过重定向的URL将其发送回客户端。
- 获取访问令牌:客户端通过向授权服务器发出请求来用授权码换得访问令牌。
- 访问资源:客户端使用访问令牌向资源服务器请求受保护的资源。资源服务器验证令牌后返回请求的数据。
一些常用的 OAuth 2.0 授权方式
- 授权码流程(最常见的流程)
-
适用于需要用户交互的 web 应用程序。
-
客户端在获得用户同意后,用授权码交换访问令牌。
- 隐式流程(不推荐使用)
- 设计用于公共客户端,例如单页应用程序。
- 用户直接获取访问令牌,而不是授权码。
- 出于安全考虑,我们不再推荐此流程。
- 资源所有者的密码凭证流程(有限使用)
- 用户直接将他们的用户名和密码提供给客户端。
- 客户端用这些信息请求访问令牌。
- 不建议公开应用这样做,因为存在安全隐患。
- 客户端凭证流程(机器到机器)
-
当客户端应用程序需要访问其自身的资源,而不是代表用户操作时使用。
- 在服务间API访问中较为常见。
优缺点
好处
- 灵活性 :支持多种授权方式,适用于不同类型的客户端和应用场景的需求。
- 安全性 :通过将授权与认证分开,OAuth 2.0 增强了安全性。它不直接使用用户名和密码进行访问控制,而是依赖于令牌进行访问控制。
缺点
- 复杂性:实现和配置 OAuth 2.0 可能会比较棘手,需要妥善处理 令牌管理 和 安全配置。
- 安全风险:如果令牌泄露,将带来安全风险。因此,必须采取适当的安全措施,比如使用 HTTPS 和安全的令牌管理策略。
代码示例
这里有一个用Express实现的OAuth 2.0认证的例子:
const express = require('express');
const axios = require('axios');
const app = express();
// OAuth 2.0 设置
const clientId = 'your-client-id';
const clientSecret = 'your-client-secret';
const redirectUri = 'http://localhost:3000/callback';
const authorizationServerUrl = 'https://authorization-server.com';
const resourceServerUrl = 'https://resource-server.com';
// 登录路由 - 将用户重定向至授权服务器
app.get('/login', (req, res) => {
const authUrl = `${authorizationServerUrl}/authorize?response_type=code&client_id=${clientId}&redirect_uri=${redirectUri}&scope=read`;
res.redirect(authUrl);
});
// 回调路由 - 处理授权码交换
app.get('/callback', async (req, res) => {
const { code } = req.query;
if (!code) {
return res.status(400).send('缺少授权码');
}
try {
// 用授权码交换访问令牌
const response = await axios.post(`${authorizationServerUrl}/token`, {
grant_type: 'authorization_code',
code,
redirect_uri: redirectUri,
client_id: clientId,
client_secret: clientSecret,
});
const { access_token } = response.data;
// 使用访问令牌获取受保护的资源
const resourceResponse = await axios.get(`${resourceServerUrl}/user-info`, {
headers: { Authorization: `Bearer ${access_token}` },
});
res.json(resourceResponse.data);
} catch (error) {
res.status(500).send('令牌交换或资源访问时出错了');
}
});
app.listen(3000, () => {
console.log('服务器已在端口 3000 上监听...');
});
全屏,退出全屏
结束语这四种认证方法每一种都有其各自的优势、劣势和适用场合。
- 会话模式:非常适合简单的服务器端渲染应用。
- JWT:适合现代无状态架构和移动应用的场景。
- 单点登录(SSO):最适合拥有多个相关服务的企业环境。
- OAuth 2.0:是处理第三方集成和API访问的首选。
……
我们是 Leapcell,你的 Node.js 项目托管的最佳选择
(链接: https://leapcell.io/?lc_t=d_jsauth)
Leapcell(https://leapcell.io/?lc_t=d_jsauth)是新一代的无服务器平台,适用于网页托管、异步任务以及 Redis 缓存。
多语言兼容性
- 用 Node.js、Python、Go、Rust 等编程。
免费部署无数项目
只为您实际使用的部分付费 — 不用不收钱。
超高的性价比
- 按需计费,无闲置时间费用。
- 例如:$25支持6.94百万个请求,平均响应延时为60毫秒。
简化的开发过程
- 简直观的用户界面,轻松搞定设置。
- 完全自动化的CI/CD流水线和GitOps集成,让操作更加高效。
- 实时指标和日志,帮助您获得可操作的洞察。
轻松扩展和高性能
- 自动伸缩,轻松应对高并发。
- 零运维负担,只需关注开发。
了解更多,请访问文档!
关注我们在X账号: @LeapcellHQ
在我们的博客上阅读了解有关Session、JWT、SSO、OAuth的优缺点和应用场景的文章。
共同学习,写下你的评论
暂无评论
作者其他优质文章