使用 NodeJS 进行用户身份验证的不同方法(第二部分)基于 JWT 令牌的身份验证

2025-05-27

使用 NodeJS 进行用户身份验证的不同方法(第二部分)(JWT)

基于令牌的身份验证

这是 NodeJS 用户身份验证的第二部分。您可以点击此处查看第一部分。本部分我们将讨论更可行、更可扩展的现代用户身份验证解决方案——基于 Token 的身份验证。

基于令牌的身份验证

客户端.png

在基于令牌的身份验证中,当用户使用正确的凭据登录时,会生成一个令牌(一个包含随机字符和数字的长字符串),并将其发送回客户端浏览器,并存储在本地存储 (localStorage)、会话存储 (SessionStorage) 或 Cookie 中。现在,每次用户向服务器发出请求时,存储在浏览器中的令牌都会被发送回服务器,我们会使用一些中间件函数来验证令牌并返回所需的资源。
让我们用代码来实现它。

创建一个空的 NodeJS 项目并在终端运行命令

npm install express jsonwebtoken mongoose

express - 用于创建我们的服务器
mongoose - 用于连接到我们的 MongoDB 数据库
jsonwebtoken - 称为 JWT,它是一个用于安全地生成访问令牌的开源 npm 包

const express = require('express');
const app = express();
const mongoose = require('mongoose');
const jwt = require('jsonwebtoken');

await mongoose.connect('your_mongo_url', (err, db) => {
            console.log('MongoDB Connected....');
      });

app.get('/', (req,res)=>{
    res.send('<h1>Hello World!</h1>'); 
})

app.listen(5000, () => console.log(`Server 🔥🔥🔥 up on 5000`));
Enter fullscreen mode Exit fullscreen mode

这段代码将使我们的服务器在端口 5000 上启动并运行。因此,如果您现在访问http://localhost:5000/,您将看到所需的结果。

app.post("/login", async (req, res) => {
  try {
    const { username, password } = req.body;
    const user = await User.findOne({ username });
    if (!user) {
      return res.json({ msg: "Please enter a valid username" });
    }
    const accessToken = jwt.sign(
        { username, id: user._id },
        JWT_SECRET,
        {
          expiresIn: process.env.NODE_ENV === "production" ? "6h" : "2 days",
        }
      );
      res.json({ msg: "User logged in!", accessToken });
  } catch (err) {
    console.log(err);
    res.status(503).json({ msg: "Server error!" });
  }
});

Enter fullscreen mode Exit fullscreen mode

上面的代码块用于提交登录凭据并登录用户。让我们了解一下jwt.sign()创建访问令牌的功能。JWT
(Json Web Token)有一个名为 的方法sign(),用于创建一个新的 Web 令牌,该令牌将以隐藏的方式包含用户信息。该jwt.sign()方法有三个参数。我们来分别介绍一下。

  1. 首先是要存储在令牌中的数据。它可以是字符串或 JavaScript 对象。在本例中,我们将用户名和 ID(MongoDB 生成的唯一 ID)存储在访问令牌中。

  2. 第二个参数是JWT_SECRET。它可以是任何值(随机字符串),重要的是不要在生产环境中显示它。您应该使用环境变量来保存 JWT_SECRET。它稍后将用于验证 JWT Token 并验证用户身份。

  3. 第三个参数是可以为访问令牌定义的可选属性,例如到期日期、httpOnly 等。您可以在此处查看有关可选参数的更多详细信息

此函数将返回一串随机字符,称为 JWT 访问令牌。如下所示: 现在,如果您知道此令牌包含有关用户的信息,请在浏览器中打开另一个标签页,然后转到https://jwt.io/,并在编码的输入框中粘贴上述访问令牌,您将收到如下所示的 ID 和用户名。

eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjYwZndmNzA5N2ZmN2YwOTdmMDk5IiwidXNlcm5hbWUiOiJsYXZpc2hnb3lhbCJ9.kNPmoyim0KbrHw6Fl2NPdUWO3UdZ1cr3rFH4eZy9DIg

屏幕截图-2021-11-21-095657.png

如果仔细观察,会发现 JWT 访问令牌中有两个点,将令牌字符串分为三部分。
屏幕截图-2021-11-21-100033.png

第一部分是用于编码令牌的算法,第二部分包含我们输入的用户详细信息,第三部分是用于稍后验证用户的 JWT 密钥(我们刚才会这样做)

const authenticateToken = (req, res, next) => {
  const authHeader = req.headers["authorization"];
  const token = authHeader && authHeader.split(" ")[1];
  if (token === null) return res.status(401).json({ msg: "Not Authorized" });
  jwt.verify(token, JWT_SECRET, (err, user) => {
    if (err) return res.status(401).json({ msg: err });
    req.user = user;
    next();
  });
};
Enter fullscreen mode Exit fullscreen mode

这段代码将验证传入的 JWT 令牌并对用户进行身份验证,然后我们就可以进行进一步的数据处理了。jwt.verify()它接受三个参数,第一个是从客户端接收的令牌。令牌可以通过 Cookie 或标头接收。这里,令牌通过标头AuthorizationHeader 传递。*请记住,整个项目中的 JWT_SECRET 必须相同,否则 JWT 令牌将无法解码,并返回无效令牌的错误。*

现在,上述 authenticToken 中间件函数可用于所有受保护的路由,以验证用户是否有资格访问该特定路由的数据,例如:

app.get("/dashboard", authenticateToken, (req,res)=>{
   res.send('<h1>Welcome to dashboard</h1>')
})
Enter fullscreen mode Exit fullscreen mode

因此,在上面的代码中,我们使用了 authenticToken 作为中间件函数,如果客户端的请求包含正确的 jwt 令牌,则将显示“欢迎来到仪表板”标题,否则将显示错误。

好了,各位,以上就是关于 NodeJS 身份验证和授权的全部内容。虽然有很多更复杂、更安全的身份验证方法,但这是一个初学者教程,所以我就不多说了。我会在下一篇博客中详细介绍。到时候请分享这篇文章并在 Twitter 上标记我。
再见!
给我买杯咖啡

文章来源:https://dev.to/lavig10/ Different-ways-for-user-authentication-with-nodejs-part-2-jwt-3h0p
PREV
更好的代码审查实践
NEXT
JavaScript 的层次