该使用哪种身份验证?四种常用方法的比较

2025-06-09

该使用哪种身份验证?四种常用方法的比较

覆盖

在前端项目开发中,用户认证主要有四种方式:Session、JWT、SSO、OAuth 2.0

那么,这四种方法各有什么优缺点呢?今天,我们就来比较一下吧!

经典的基于会话的身份验证

什么是基于会话的身份验证?

基于会话的身份验证是前端和后端系统中常用的用户身份验证方法。

它主要依靠服务器来创建和管理用户会话。

会话如何工作

会话认证过程包括六个步骤:

  1. 用户登录:用户在登录页面输入其凭证(例如用户名和密码)。这些凭证由前端发送到后端服务器进行验证。
  2. 创建会话:验证凭证后,后端服务器会创建一个会话,通常包括一个唯一的会话 ID,该 ID 存储在服务器上。
  3. 返回 Session ID:服务器通常通过 Cookie 将 Session ID 发送回前端。此 Cookie 存储在用户浏览器中,并将在后续请求中自动发送。
  4. 存储会话 ID:浏览器会保存 Cookie,并自动将其包含在发送到服务器的每个请求中。这允许服务器识别用户的会话并对其进行身份验证。
  5. 会话验证:服务器查找会话 ID 并验证相关会话信息以确定用户身份。它还可以使用会话数据进行权限检查和访问控制。
  6. 会话过期和管理:服务器可以设置会话过期时间,并定期清除过期的会话。当用户注销或会话超时时,服务器将删除或使会话失效。

从上面的流程可以看出,基于会话的身份验证中,前端不需要主动参与,关键操作都在浏览器和服务器之间处理。

优点和缺点

优势

  • 简单易用:管理会话和用户身份验证对于开发人员来说相对简单。
  • 兼容性好:大多数浏览器都支持cookies,可以实现自动发送和接收。

缺点

  • 可扩展性差:在分布式系统中,多台服务器可能需要共享会话存储,从而增加复杂性。
  • 需要 HTTPS:如果 Cookie 被盗,可能会导致会话劫持。因此,应使用 HTTPS 来保护数据传输,并采取其他安全措施(例如,设置带有HttpOnlySecure属性的 Cookie)。

示例代码

以下是使用Express实现会话身份验证的示例

const express = require('express');
const session = require('express-session');
const app = express();

// Configure and use express-session middleware
app.use(
  session({
    secret: 'your-secret-key', // Key used to sign the session ID cookie, ensuring session security
    resave: false, // Whether to save the session on every request, even if it hasn’t changed
    saveUninitialized: true, // Whether to save an uninitialized session
    cookie: {
      secure: true, // Whether to send cookies only over HTTPS (requires HTTPS support)
      maxAge: 24 * 60 * 60 * 1000, // Cookie expiration time (set to 24 hours)
    },
  })
);

// Login route handler
app.post('/login', (req, res) => {
  // Authenticate user (assume the user has been validated)
  const user = { id: 123 }; // Example user ID
  req.session.userId = user.id; // Store user ID in session
  res.send('Login successful');
});

app.get('/dashboard', (req, res) => {
  if (req.session.userId) {
    // If the session contains a user ID, the user is logged in
    res.send('Dashboard content...');
  } else {
    // If no user ID is found in the session, the user is not logged in
    res.send('Please log in...');
  }
});

app.listen(3000, () => {
  console.log('Server is listening on port 3000...');
});
Enter fullscreen mode Exit fullscreen mode

JWT(JSON Web 令牌)身份验证

什么是 JWT 身份验证?

JWT认证是目前最常用的认证方式之一。

服务端返回一个代表用户身份的token,在请求中会把token添加到请求头中,用于用户验证。

由于 HTTP 请求是无状态的,因此这种方法也称为无状态身份验证

JWT 的工作原理

  1. 用户登录:用户在登录页面输入其凭证(例如用户名和密码),这些凭证被发送到后端服务器进行验证。
  2. 生成 JWT:验证用户凭证后,后端服务器会生成一个 JWT。此令牌通常包含基本用户信息(例如用户 ID)和元数据(例如到期时间)。
  3. 返回 JWT:服务器将生成的 JWT 发送回前端,通常以 JSON 响应的形式。
  4. 存储 JWT:前端将 JWT 存储在客户端,通常存储在 中localStorage。极少数情况下,也可能存储在 Cookie 中,但这会带来跨站脚本(XSS)跨站请求伪造(CSRF)等安全风险。
  5. 使用 JWT 进行请求:进行 API 调用时,前端将 JWT 令牌附加在Authorization标头中(格式Bearer <token>:)并将其发送到服务器。
  6. 验证 JWT:服务器收到请求后,提取 JWT,验证其有效性(例如检查签名和过期时间)。如果有效,服务器将处理该请求并返回相应的资源或数据。
  7. 响应请求:服务器处理请求并返回响应,前端可以根据需要使用该响应。

优点和缺点

优势

  • 无状态: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'; // Secret key for signing and verifying JWTs

// Login route that generates a JWT
app.post('/login', (req, res) => {
  const { username, password } = req.body;
  // User authentication (assuming the user is valid)
  const user = { id: 1, username: 'user' }; // Example user data
  const token = jwt.sign(user, secretKey, { expiresIn: '24h' }); // Generate JWT
  res.json({ token }); // Return JWT
});

// Protected route
app.get('/dashboard', (req, res) => {
  const token = req.headers['authorization']?.split(' ')[1];
  if (!token) {
    return res.status(401).send('No token provided');
  }
  jwt.verify(token, secretKey, (err, decoded) => {
    if (err) {
      return res.status(401).send('Invalid token');
    }
    res.send('Dashboard content');
  });
});

app.listen(3000, () => {
  console.log('Server is listening on port 3000...');
});
Enter fullscreen mode Exit fullscreen mode

SSO(单点登录)身份验证

什么是 SSO 身份验证?

SSO 身份验证通常用于“基于套件”的应用程序中。通过中央登录系统,用户只需登录一次即可访问多个应用程序,而无需重新进行身份验证。

SSO 的工作原理

  1. 用户访问应用程序:用户尝试访问需要身份验证的应用程序(称为服务提供商(SP))。
  2. 重定向到身份提供商 (IdP):由于用户未登录,应用程序会将其重定向到SSO 身份提供商 (IdP)(通常称为登录中心)。登录中心负责处理用户身份验证。
  3. 用户登录:用户在登录中心输入其凭证。如果用户已登录(例如,已登录公司内部的单点登录系统),则可以跳过此步骤。
  4. SSO 令牌生成:一旦通过身份验证,身份提供者就会生成一个SSO 令牌(例如,OAuth 令牌或 SAML 断言)并将用户重定向回原始应用程序,并附加该令牌。
  5. 令牌验证:应用程序(服务提供商)接收令牌并将其发送给 SSO 身份提供商进行验证。IdP 验证令牌后返回用户的身份信息。
  6. 用户获得访问权限:身份验证成功后,应用程序将根据用户的身份信息授予访问权限。用户现在可以访问应用程序的受保护资源。
  7. 访问其他应用程序:如果用户访问也使用同一登录中心的其他应用程序,则会被重定向到登录中心。由于用户已登录,登录中心会自动进行身份验证,并将其重定向回目标应用程序,从而实现无缝登录

优点和缺点

优势

  • 简化用户体验:用户只需登录一次即可访问多个应用程序,减少重复登录的工作。
  • 集中管理:管理员可以集中管理用户身份和访问权限,提高效率和安全性。
  • 增强安全性:降低密码泄露风险,因为用户只需记住一个密码。此外,还可以强制实施更强大的身份验证机制(例如,多重身份验证,MFA)。

缺点

  • 单点故障:如果登录中心(SSO 身份提供者)遇到问题,所有依赖它的应用程序都可能会受到影响。
  • 复杂的实施:部署和维护 SSO 解决方案可能很复杂,需要适当的安全配置和系统之间的互操作性。

常见的SSO实现技术

SAML(安全断言标记语言)

  • 一种基于 XML 的标准,用于在身份提供商 (IdP) 和服务提供商 (SP) 之间交换身份验证和授权数据。
  • 常用于企业环境。

OAuth 2.0 和 OpenID Connect

  • OAuth 2.0是一个用于授予第三方访问用户资源的授权框架。
  • OpenID Connect建立在 OAuth 2.0 之上,为用户身份验证添加了身份层。
  • 常用于网络和移动应用程序

CAS(中央认证服务)

  • 一个针对 Web 应用程序的开源 SSO 解决方案,允许用户进行一次身份验证并访问多项服务。

OAuth 2.0身份验证

什么是 OAuth 2.0 身份验证?

OAuth 2.0 是用于授权第三方应用访问用户资源的标准协议。示例包括:

  • Facebook 登录
  • Discord 登录
  • App二维码登录

OAuth 2.0 主要用于授权而不是身份验证,但它通常与身份验证结合使用以实现用户登录。

OAuth 2.0 的工作原理

OAuth 2.0 很复杂,因此在了解其流程之前,我们需要澄清一些关键概念

OAuth 2.0 中的关键概念

  • 资源所有者:通常是拥有受保护资源(例如个人数据、文件)的用户。
  • 资源服务器:托管受保护资源并确保只有授权用户才能访问的服务器。
  • 客户端:想要访问受保护资源的应用程序或服务。客户端必须获得资源所有者的授权。
  • 授权服务器:负责验证资源所有者身份并向客户端授予授权的服务器。它颁发访问令牌,允许客户端访问资源服务器。

OAuth 2.0 工作流程

  1. 用户授予授权:当用户与客户端应用程序交互时,应用程序会请求授权以访问用户的资源。用户将被重定向到授权服务器
  2. 获取授权码:如果用户同意,授权服务器将生成授权码并将其发送回客户端(通过重定向 URL)。
  3. 获取访问令牌:客户端通过向授权服务器发出请求来交换访问令牌授权码。
  4. 访问资源:客户端使用访问令牌 (Access Token)向资源服务器 (Resource Server)请求受保护的资源。资源服务器验证令牌后,返回请求的数据。

常见的 OAuth 2.0 授权类型(授权流程)

  1. 授权码流程(最常见)
    • 适用于需要用户交互的Web应用程序。
    • 客户端在获得用户同意后,用授权码交换访问令牌。
  2. 隐式流程(不推荐)
  • 专为公共客户(例如单页应用程序)设计。
  • 用户直接收到访问令牌而不是授权码。
  • 出于安全考虑,不再推荐此流程。
  1. 资源所有者密码凭证流程(限制使用)
  • 用户直接向客户端提供其用户名和密码。
  • 客户端使用这些凭证请求访问令牌。
  • 由于存在安全风险,不建议用于面向公众的应用程序。
  1. 客户端凭证流(机器对机器)
    • 当客户端应用程序需要访问其自己的资源而不是代表用户行事时使用。
    • 适用于服务之间的 API 访问。

优点和缺点

优势

  • 灵活性:支持多种授权流程,适用于不同的客户端类型和应用场景。
  • 安全性:通过分离授权身份验证,OAuth 2.0 增强了安全性。它不再使用用户名和密码,而是依靠令牌进行访问控制。

缺点

  • 复杂性:实施和配置 OAuth 2.0 可能具有挑战性,需要适当的令牌管理安全配置
  • 安全风险:如果令牌泄露,可能会带来安全风险。因此,必须采取适当的安全措施(例如,使用 HTTPS 和安全的令牌管理策略)。

示例代码

以下是OAuth 2.0 身份验证的Express实现:

const express = require('express');
const axios = require('axios');
const app = express();

// OAuth 2.0 Configuration
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';

// Login route - Redirects user to the Authorization Server
app.get('/login', (req, res) => {
  const authUrl = `${authorizationServerUrl}/authorize?response_type=code&client_id=${clientId}&redirect_uri=${redirectUri}&scope=read`;
  res.redirect(authUrl);
});

// Callback route - Handles Authorization Code exchange
app.get('/callback', async (req, res) => {
  const { code } = req.query;
  if (!code) {
    return res.status(400).send('Authorization code is missing');
  }

  try {
    // Exchange authorization code for an access token
    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;

    // Use the access token to fetch protected resources
    const resourceResponse = await axios.get(`${resourceServerUrl}/user-info`, {
      headers: { Authorization: `Bearer ${access_token}` },
    });

    res.json(resourceResponse.data);
  } catch (error) {
    res.status(500).send('Error during token exchange or resource access');
  }
});

app.listen(3000, () => {
  console.log('Server is listening on port 3000...');
});
Enter fullscreen mode Exit fullscreen mode

结论

这四种身份验证方法各有其优点、缺点和适用用例

  • 会话:适用于简单的服务器呈现应用程序。
  • JWT:适用于现代无状态架构和移动应用程序。
  • SSO:最适合具有多种相关服务的企业环境。
  • OAuth 2.0:第三方集成和 API 访问的首选。

我们是 Leapcell,您托管 Node.js 项目的首选。

Leapcell

Leapcell是用于 Web 托管、异步任务和 Redis 的下一代无服务器平台:

多语言支持

  • 使用 Node.js、Python、Go 或 Rust 进行开发。

免费部署无限项目

  • 仅按使用量付费 — 无请求,无费用。

无与伦比的成本效益

  • 按使用量付费,无闲置费用。
  • 例如:25 美元支持 694 万个请求,平均响应时间为 60 毫秒。

简化的开发人员体验

  • 直观的用户界面,轻松设置。
  • 全自动 CI/CD 管道和 GitOps 集成。
  • 实时指标和日志记录可提供可操作的见解。

轻松的可扩展性和高性能

  • 自动扩展以轻松处理高并发。
  • 零运营开销——只需专注于建设。

在文档中探索更多

尝试 Leapcell

在 X 上关注我们:@LeapcellHQ


阅读我们的博客

鏂囩珷鏉ユ簮锛�https://dev.to/leapcell/which-authentication-to-use-a-comparison-of-4-popular-approaches-24jc
PREV
Nutanix 全栈(Nodejs + Reactjs)面试经历
NEXT
掌握 Express.js:深入探究