介绍
JSON Web Tokens(JWTs)支持授权和信息交流。
一个常见的用例是允许客户端在登录后保留会话信息. 通过本地存储会话信息并在提出请求时将其传送到服务器进行身份验证,服务器可以信任客户端是注册用户。
<$>[警告] 警告: 请注意在 localStorage 中存储 JWT 的安全风险。
在本文中,您将了解使用 Node.js 和 Vanilla JavaScript 的服务器-客户端关系中的 JWT 应用程序。
前提条件
要跟随这篇文章,您将需要下列在您的机器上安装:
- Node.js 是本地安装的,您可以按照 如何安装 Node.js 和创建本地开发环境进行操作。
步骤 1 - 生成一个代币
「jsonwebtoken」是JSON Web Token的实现。
您可以通过在终端中运行以下命令将其添加到您的 JavaScript 项目中:
1npm install jsonwebtoken
然后将其导入到您的文件中,如下:
1const jwt = require('jsonwebtoken');
要签署一个代币,你需要三个信息:
- 代币秘密
- 代币中的数据片
- 代币到期时间
token secret 是一个长的随机字符串,用于加密和解密数据。
要生成这个秘密,一个选项是使用Node.js的内置加密
库,如下:
1> require('crypto').randomBytes(64).toString('hex')
2// '09f26e402586e2faa8da4c98a35f1b20d6b033c6097befa8be3486a829587fe2f90a832bd3ff9d42710a4da095a2ce285b009f0c3730cd9b8e1af3eb84df6611'
<$>[警告]
警告: 要小心!如果你的秘密
很简单,代币验证过程将更容易被未经授权的入侵者打破。
现在,将此秘密存储在您的项目的 .env
文件中:
1[label .env]
2TOKEN_SECRET=09f26e402586e2faa8da4c98a35f1b20d6b033c60...
要将这个代币带入 Node.js 文件并使用它,您必须使用dotenv
:
1npm install dotenv
然后将其导入到您的文件中,如下:
1const dotenv = require('dotenv');
2
3// get config vars
4dotenv.config();
5
6// access config var
7process.env.TOKEN_SECRET;
您在代码中哈希的 piece of data 可以是用户 ID 或用户名或更复杂的对象,在任何情况下,它都应该是 identifier 用于 specific 用户。
代币到期时间是一个字符串,例如1800秒(30分钟),它详细说明了代币是否有效。
以下是签署代币的函数的例子:
1function generateAccessToken(username) {
2 return jwt.sign(username, process.env.TOKEN_SECRET, { expiresIn: '1800s' });
3}
这可以从用户登录或登录请求发送回来:
1app.post('/api/createNewUser', (req, res) => {
2 // ...
3
4 const token = generateAccessToken({ username: req.body.username });
5 res.json(token);
6
7 // ...
8});
此示例从req
(request)中取出username
值,并提供代币为res
(response)。
这结论了如何jsonwebtoken
,crypto
和dotenv
可以用来生成JWT。
步骤 2 – 验证一个代币
在 Express.js应用程序中实现 JWT 身份验证系统的方法有很多。
一个方法是使用 Express.js 中的 middleware功能。
它是如何工作的,当对特定路径提出请求时,您可以将 (req, res)
变量发送给中间函数,而不是在 app.get((req, res) => {})
中指定的变量。
中间件是一个函数,其参数为(req, res, next)。
- 「req」是发送的请求([GET, POST, DELETE, PUT,等])。
*「res」是可以以多种方式返回用户的响应(
res.sendStatus(200)
,res.json()
,等等)。 *「next」是可以调用来将执行程序通过中间件移动到实际的「app.get」服务器响应 的函数。
以下是用于身份验证的 middleware 函数示例:
1const jwt = require('jsonwebtoken');
2
3function authenticateToken(req, res, next) {
4 const authHeader = req.headers['authorization']
5 const token = authHeader && authHeader.split(' ')[1]
6
7 if (token == null) return res.sendStatus(401)
8
9 jwt.verify(token, process.env.TOKEN_SECRET as string, (err: any, user: any) => {
10 console.log(err)
11
12 if (err) return res.sendStatus(403)
13
14 req.user = user
15
16 next()
17 })
18}
使用此中间件函数的示例请求会像这样:
1GET https://example.com:4000/api/userOrders
2Authorization: Bearer JWT_ACCESS_TOKEN
一个使用该中间件的请求的例子会像这样的东西:
1app.get('/api/userOrders', authenticateToken, (req, res) => {
2 // executes after authenticateToken
3 // ...
4})
此代码将验证客户提供的代币,如果是有效的,它可以继续请求,如果不是有效的,它可以被视为错误。
步骤3 – 处理客户端代币
当客户端收到代币时,他们通常希望存储该代币以便在未来的请求中收集用户信息。
存储auth代币的最流行的方法是在HttpOnly
cookie中。
以下是使用客户端JavaScript代码存储cookie的实现:
1// get token from fetch request
2const token = await res.json();
3
4// set token in cookie
5document.cookie = `token=${token}`
这种方法会将响应存储在本地,以便在未来向服务器发送请求。
这结束了请求一个代币,生成一个代币,接收一个代币,通过一个代币与新的请求,并验证一个代币的流程。
结论
在本文中,您介绍了JWTs和应用它们到Node.js应用的一个方法,这种方法依赖于jsonwebtoken
,crypto
,dotenv
和express
的组合。
对于使用 JWT 的另一种方法,有 如何使用 JSON Web Tokens 和 Passport 实现 API 身份验证。
有关JWT的更多背景,有 介绍
文档。
如果您想了解有关 Node.js 的更多信息,请参阅 我们的 Node.js 主题页面以获取练习和编程项目。