使用 NodeJS 进行用户身份验证的不同方法(第二部分)(JWT)
基于令牌的身份验证
这是 NodeJS 用户身份验证的第二部分。您可以点击此处查看第一部分。本部分我们将讨论更可行、更可扩展的现代用户身份验证解决方案——基于 Token 的身份验证。
基于令牌的身份验证
在基于令牌的身份验证中,当用户使用正确的凭据登录时,会生成一个令牌(一个包含随机字符和数字的长字符串),并将其发送回客户端浏览器,并存储在本地存储 (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`));
这段代码将使我们的服务器在端口 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!" });
}
});
上面的代码块用于提交登录凭据并登录用户。让我们了解一下jwt.sign()
创建访问令牌的功能。JWT
(Json Web Token)有一个名为 的方法sign()
,用于创建一个新的 Web 令牌,该令牌将以隐藏的方式包含用户信息。该jwt.sign()
方法有三个参数。我们来分别介绍一下。
-
首先是要存储在令牌中的数据。它可以是字符串或 JavaScript 对象。在本例中,我们将用户名和 ID(MongoDB 生成的唯一 ID)存储在访问令牌中。
-
第二个参数是
JWT_SECRET
。它可以是任何值(随机字符串),重要的是不要在生产环境中显示它。您应该使用环境变量来保存 JWT_SECRET。它稍后将用于验证 JWT Token 并验证用户身份。 -
第三个参数是可以为访问令牌定义的可选属性,例如到期日期、httpOnly 等。您可以在此处查看有关可选参数的更多详细信息
此函数将返回一串随机字符,称为 JWT 访问令牌。如下所示: 现在,如果您知道此令牌包含有关用户的信息,请在浏览器中打开另一个标签页,然后转到https://jwt.io/,并在编码的输入框中粘贴上述访问令牌,您将收到如下所示的 ID 和用户名。
eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjYwZndmNzA5N2ZmN2YwOTdmMDk5IiwidXNlcm5hbWUiOiJsYXZpc2hnb3lhbCJ9.kNPmoyim0KbrHw6Fl2NPdUWO3UdZ1cr3rFH4eZy9DIg
如果仔细观察,会发现 JWT 访问令牌中有两个点,将令牌字符串分为三部分。
第一部分是用于编码令牌的算法,第二部分包含我们输入的用户详细信息,第三部分是用于稍后验证用户的 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();
});
};
这段代码将验证传入的 JWT 令牌并对用户进行身份验证,然后我们就可以进行进一步的数据处理了。jwt.verify()
它接受三个参数,第一个是从客户端接收的令牌。令牌可以通过 Cookie 或标头接收。这里,令牌通过标头Authorization
Header 传递。*请记住,整个项目中的 JWT_SECRET 必须相同,否则 JWT 令牌将无法解码,并返回无效令牌的错误。*
现在,上述 authenticToken 中间件函数可用于所有受保护的路由,以验证用户是否有资格访问该特定路由的数据,例如:
app.get("/dashboard", authenticateToken, (req,res)=>{
res.send('<h1>Welcome to dashboard</h1>')
})
因此,在上面的代码中,我们使用了 authenticToken 作为中间件函数,如果客户端的请求包含正确的 jwt 令牌,则将显示“欢迎来到仪表板”标题,否则将显示错误。
好了,各位,以上就是关于 NodeJS 身份验证和授权的全部内容。虽然有很多更复杂、更安全的身份验证方法,但这是一个初学者教程,所以我就不多说了。我会在下一篇博客中详细介绍。到时候请分享这篇文章并在 Twitter 上标记我。
再见!