Node.js服务器端身份验证:令牌与JWT
#网络开发人员 #node #jwt

Destiny Erhaborâ!

撰写

在现代网络开发中,身份验证是确保应用程序的关键部分。这两种最受欢迎​​的方法包括使用令牌和客户端身份验证的服务器端身份验证使用JSON Web令牌(JWT)。

这两种方法都有自己独特的优势和缺点,并且决定使用哪种方法取决于您特定应用程序的要求。在本文中,我们将比较方法并突出每种方法的好处和缺点。让我开始!

跳跃:

无状态与状态身份验证

在Web应用程序中,身份验证是验证想要访问受限制资源的用户身份的过程。您可以使用几种不同类型的身份验证,例如用户名和密码身份验证,社交登录或生物识别认证。

无状态身份验证

在无状态身份验证中,服务器不会存储有关用户的任何会话信息。取而代之的是,用户对服务器提出的每个请求都包含所有必要的身份验证信息,通常以JWT的形式。然后,服务器验证令牌并做出相应的响应。

无状态身份验证在现代Web应用程序中很受欢迎,因为它是可扩展的,可以是used with the microservices architecture

状态身份验证

在状态身份验证中,服务器将有关用户的会话信息存储在数据库或内存中缓存中。当用户登录时,服务器会创建一个会话ID并将其存储在服务器端。然后,该会话ID用于身份验证用户提出的后续请求。

状态身份验证的可扩展性不如无状态身份验证,因为它要求服务器维护状态,这可能会成为大型用户基础的问题。

什么是服务器端令牌?

使用服务器端令牌(也称为基于会话的身份验证)是陈述身份验证的一个示例,涉及将用户身份验证数据存储在服务器上。成功身份验证后,服务器为用户生成一个唯一的令牌,然后将其存储在服务器的内存或数据库中。然后将令牌发送回客户,无论是饼干还是在响应主体中。

带有令牌的服务器端身份验证涉及为每个用户登录时为每个用户创建一个唯一的会话令牌。令牌存储在服务器端上,并用于对同一用户的后续请求进行身份验证。

相比之下,使用JWT使用JWT的客户端身份验证涉及在成功登录后向客户发出签名令牌,然后将其存储在客户端端,并在每个后续请求时发送回服务器。

使用服务器端身份验证 的优点

容易无效

服务器端身份验证很容易无效,因为我们可以完全控制服务器上存储的会话数据。如果我们怀疑任何欺诈活动,我们可以快速终止用户的会话或撤销令牌,从而提供额外的安全层。

没有存储限制

与客户端的身份验证不同,在存储空间仅限于cookie或本地存储的情况下,我们可以在服务器上存储任何数量的会话数据,并使用服务器端身份验证。这使得存储大量数据(例如用户首选项或历史记录)变得更加容易。

更好地适合合规性

要符合合规法规,一些监管机构要求将会话数据存储在服务器端。这旨在在受控和安全的环境中增强数据安全性,隐私和对敏感信息的控制。在这些情况下,服务器端身份验证是更好的选择。

一些示例包括付款卡行业数据安全标准(PCI DSS)和《健康保险可移植性与问责制法》(HIPAA)。

无需重新认证

使用服务器端身份验证,您无需在每个请求上重新认证用户,这可以改善应用程序的性能。

服务器端身份验证 的缺点

可伸缩性问题

随着用户和会话的数量增加,将所有会话数据存储在服务器上可能会引起可扩展性问题。它需要更多的内存和CPU资源,这可能会导致响应时间较慢并总体上降低性能。

复杂

服务器端身份验证可以很复杂,可以实现和维护,尤其是当您需要在多个服务器或实例上存储会话数据时。它需要更多的代码,配置和基础架构。

成本

由于它需要更多的资源和基础架构,因此服务器端身份验证可能比客户端身份验证更昂贵。

没有离线访问

由于所有会话数据都存储在服务器上,因此没有可用的离线访问,在某些情况下可能是不利的。

使用Node.js应用程序 的服务器端身份验证

让我们查看服务器端身份验证方法的简单代码实现。首先,我们需要安装express-session和node.js的快递软件包。我们可以通过运行以下代码来做到这一点:

npm install express express-session

接下来,我们将创建一个简单的index.js文件:

const express = require("express");
const session = require("express-session");
const app = express();
// Dummy user object to demonstrate
const users = [
  { id: 1, username: "john", password: "password" },
  { id: 2, username: "jane", password: "password" },
];
// Array to hold blacklisted user IDs
const blacklistedUsers = [];
// Middleware to parse JSON request bodies
app.use(express.json());
// Middleware to initialize the session
app.use(
  session({
    secret: "mysecretkey",
    resave: false,
    saveUninitialized: true,
  })
);

// Login endpoint
app.post("/login", (req, res) => {
  const { username, password } = req.body;
  // Find the user by username and password
  const user = users.find(
    (u) => u.username === username && u.password === password
  );
  if (user) {
    if (blacklistedUsers.includes(user.id)) {
      return res.status(403).send("User is blacklisted");
    }
    // Save the user ID in the session
    req.session.userId = user.id;
    // Send the user object back to the client
    res.json({ user });
  } else {
    // Send an error response if the user is not found
    res.status(401).json({ message: "Invalid username or password" });
  }
});
// Logout endpoint
app.post("/logout", (req, res) => {
  // Destroy the session to log the user out
  req.session.destroy();
  // Send a success response
  res.json({ message: "Logged out successfully" });
});
// Protected endpoint
app.get("/profile", (req, res) => {
  console.log(req.session.userId);
  // Check if the user is logged in by checking if the user ID is present in the session
  if (req.session.userId) {
    // Find the user by ID
    const user = users.find((u) => u.id === req.session.userId);
    // Send the user object back to the client
    res.json({ user });
  } else {
    // Send an error response if the user is not logged in
    res.status(401).json({ message: "Unauthorized" });
  }
});
  // Blacklist endpoint
  app.post("/blacklist", (req, res) => {
    const { userId } = req.body;
    blacklistedUsers.push(userId);
    res.send(`User ID ${userId} blacklisted`);
});
// Start the server
app.listen(3000, () => {
  console.log("Server started on port 3000");
});

上面的代码使用Express和Express-Session中间件实现服务器端身份验证。它定义了一个简单的登录和注销端点以及只能由身份验证的用户访问的受保护的配置文件端点。

当用户使用有效的用户名和密码登录时,将其用户ID保存在会话中。该用户ID从虚拟用户数组中检索user对象,并将其发送回客户端。当用户注销时,他们的会话将被销毁。

受保护的配置文件端点通过检查会话中是否存在用户ID来检查用户是否已登录。如果未登录用户,则发送错误响应。否则,从虚拟用户数组中检索了user对象并将其发送回客户端。

此实现的一个缺点是会话和黑名单用户存储在内存中,随着用户数量的增加,这可能会成为可伸缩性问题。此外,如果服务器崩溃或重新启动,则所有活动会话将丢失。为避免这些问题,您可以使用distributed caching system like Redis存储会话,而不是将其存储在内存中。

服务器端身份验证:用例

让我们查看服务器端身份验证使用令牌通常最好的方案。

安全是重中之重

由于服务器对会话代币的创建和管理具有完全控制,因此实施高级安全措施(例如IP封锁,速率限制和令牌吊销)更容易。

该应用程序需要实时更新

如果您的应用程序需要实时更新或通知,则服务器端身份验证可以更有效,因为服务器可以根据会话ID推送到客户端。

可伸缩性是一个问题

在服务器端身份验证中,会话状态存储在服务器端,可以使用Redis或Memcached等工具在多个服务器上水平缩放。

什么是JWT身份验证?

JWT authentication is a stateless, token-based authentication method。它涉及生成包含用户身份信息的令牌,然后将其发送给以存储的客户端。然后,客户端将此令牌发送给服务器以对用户进行身份验证。为了确保用户被授权访问请求的资源,在服务器上验证了令牌。

要使用JWT实现客户端身份验证,您需要在成功登录后向客户端发出签名令牌,然后将其存储在客户端。您还需要将令牌包含在每个后续请求中以对用户进行身份验证。

JWT身份验证的优点

无状态

由于令牌包含所有必要的信息来验证用户,因此服务器不需要维护任何会话数据或数据库查询。 JWT是一种无状态的身份验证方法,可以简化服务器维护并减少资源使用。

可伸缩性

JSON Web令牌允许扩展服务器资源,因为服务器不需要维护任何状态数据。

跨域

令牌是独立的,不需要访问服务器进行验证,因此可以在不同的域上使用JWT。

JWT身份验证的缺点

令牌大小

在JWT身份验证中,令牌大小可能很大。这可能会对性能产生负面影响,尤其是在每个请求随着每个请求发送的令牌时。

安全风险

如果一个令牌受到损害,攻击者可以模仿用户并获得对受保护资源的访问。另外,如果令牌未正确签名,则攻击者可以修改令牌中包含的数据。

令牌到期

如果令牌不过期,则可以无限期地使用。但是,如果代币过期过期,则可能会给用户带来不便,他们必须经常登录。平衡令牌到期时间是要考虑的关键方面。

带有node.js应用程序 的JWT身份验证

下面的代码显示了使用node.js和Express Framework的JWT身份验证的示例实现:

const express = require("express");
const jwt = require("jsonwebtoken");

const app = express();

// Dummy user object to demonstrate
const users = [
  { id: 1, username: "john", password: "password" },
  { id: 2, username: "jane", password: "password" },
];

// Secret key to sign and verify JWTs
const secretKey = "mysecretkey";

// Login endpoint
app.post("/login", (req, res) => {
  const { username, password } = req.body;

  // Find the user by username and password
  const user = users.find(
    (u) => u.username === username && u.password === password
  );

  if (user) {
    // Create a JWT token with the user ID as the payload
    const token = jwt.sign({ userId: user.id }, secretKey);

    // Send the token back to the client
    res.json({ token });
  } else {
    // Send an error response if the user is not found
    res.status(401).json({ message: "Invalid username or password" });
  }
});

// Protected endpoint
app.get("/profile", (req, res) => {
  // Get the authorization header from the request
  const authHeader = req.headers.authorization;

  if (authHeader) {
    // Extract the JWT token from the authorization header
    const token = authHeader.split(" ")[1];

    try {
      // Verify the JWT token with the secret key
      const decodedToken = jwt.verify(token, secretKey);

      // Get the user ID from the decoded token
      const userId = decodedToken.userId;

      // Find the user by ID
      const user = users.find((u) => u.id === userId);

      // Send the user object back to the client
      res.json({ user });
    } catch (error) {
      // Send an error response if the token is invalid
      res.status(401).json({ message: "Invalid token" });
    }
  } else {
    // Send an error response if the authorization header is not present
    res.status(401).json({ message: "Unauthorized" });
  }
});

// Start the server
app.listen(3000, () => {
  console.log("Server started on port 3000");
});

该代码使用koude3库生成和验证JSON Web令牌。它提供了两个端点,/login/profile

/login Endpoint期望请求主体中用户的用户名和密码发出POST请求。它在users数组中找到用户,并以用户ID作为有效负载创建JWT令牌。然后,它将令牌作为JSON对象发送回客户端。

/profile端点期望带有有效JWT令牌的授权标头的GET请求。它从标题中提取令牌,并用秘密键验证它。如果令牌有效,它将从有效载荷中提取用户ID,并在users数组中找到用户。然后,它将用户对象作为JSON对象发送回客户端。

JWT:用例

身份验证和授权

我们可以使用JWT在客户端和服务器之间安全地传输身份验证和授权数据。通过在JWT中包括用户的身份和权限,服务器可以验证用户有权访问某些资源。

单登录(SSO)

jwts是implement single-sign on (SSO)的绝佳选择,在这里,用户将登录到一个应用程序,然后能够访问其他应用程序而无需再次登录。 JWT可以在应用程序之间安全地传输用户的身份和身份验证状态。

移动应用程序

,如果传统的基于会话的身份验证方法可能不可行,则可以使用JWT在移动应用程序中对用户进行身份验证和授权。 JWT可以存储在设备上,并用于在后续请求下用服务器对用户进行身份验证。

微服务

您可以在分布式系统中使用JWT到authenticate and authorize requests between microservices。每个微服务都可以使用JWT来验证请求来自受信任的来源,并且用户被授权访问请求的资源。

服务器端令牌与JWT:摘要

令牌 jwt
存储的服务器端 存储的客户端
轻松撤销 难以撤销
需要服务器端存储 无状态
适用于实时 更适合移动或水疗中心
更新 多个域或微服务
可扩展使用Redis或Memcached 需要分布式签名或验证
更安全 更快,更易于实现

结论

总而言之,JWT身份验证是一种无状态的方法,它使用数字签名的令牌进行安全通信。它提供了简单的集成,跨域兼容性和其他安全功能。但是,重要的是要密切关注令牌大小和吊销。

服务器端令牌身份验证涉及将会话信息存储在服务器上。它提供了简单的会话管理,快速无效和对同时登录的控制。但是,它需要服务器端存储,这可能会构成可伸缩性挑战。

在JWT和服务器端令牌身份验证之间选择取决于您的用例,安全需求和可伸缩性要求。 JWT适用于无状态方案和API,而服务器端令牌最适合在Web应用程序中基于会话的身份验证。

我希望您喜欢这篇文章,如果您有任何疑问,请务必发表评论。愉快的编码!


200是只有监视器失败,生产中的网络请求缓慢

部署基于节点的Web应用程序或网站是简单的部分。确保您的节点实例继续为您的应用提供资源是艰难的地方。如果您有兴趣确保对后端或第三方服务的要求成功,try LogRocket

LogRocket Signup

LogRocket就像一个用于Web和移动应用程序的DVR一样,录制了用户与应用程序交互时发生的一切。您可以汇总并报告有问题的网络请求,以快速理解根本原因。

,您可以汇总并报告问题。

logrocket仪器您的应用程序记录基线性能时间,例如页面加载时间,第一个字节的时间,慢网络请求以及记录redux,ngrx和vuex Actions/nate。 Start monitoring for free