在现代 Web 开发中,身份认证是非常必要的。通过身份认证,我们能够保护用户的信息和数据,并确保只有授权的用户可以访问受保护的资源。在本文中,我们将介绍如何在 Express.js 中使用 JSON Web Token(JWT)进行身份认证。
什么是 JSON Web Token
JSON Web Token(JWT)是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于以 JSON 格式安全地在各方之间传输信息。JWT 可用于身份认证和授权,以及数据传输时的信息交换。
JWT 由三部分组成,分别是头部(Header)、载荷(Payload)和签名(Signature)。头部和载荷分别使用 Base64Url 编码,并通过点号(.
)分割。最后一部分是签名,它使用算法和密钥生成。因此,JWT 是由三个以点号分割的 Base64Url 编码字符串组成。
下面是一个 JWT 的示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ. SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
头部:
{ "alg": "HS256", "typ": "JWT" }
载荷:
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }
签名:使用 HMAC SHA-256 算法和共享密钥生成的字符串。
在 Express.js 中使用 JWT
要在 Express.js 中使用 JWT 进行身份认证,我们需要遵循以下几个步骤:
安装依赖
首先,我们需要安装一些必要的依赖:
npm install --save express jsonwebtoken body-parser
其中,express
是我们的 Web 框架,jsonwebtoken
是用于生成和验证 JWT 的库,body-parser
是用于解析请求体的中间件。
创建路由
我们需要创建一个路由,这个路由可以是任何需要进行身份认证的路由,比如登录、修改密码、查看个人信息等。在路由中,我们需要做以下事情:
- 获取用户提交的凭据(比如用户名和密码)。
- 验证凭据是否正确。如果凭据正确,则生成一个 JWT。
- 将 JWT 发送回客户端。
以下是一个登录路由的示例代码:
const express = require('express'); const jwt = require('jsonwebtoken'); const bodyParser = require('body-parser'); const app = express(); app.use(bodyParser.json()); app.post('/login', (req, res) => { // 获取用户提交的凭据 const { username, password } = req.body; // 验证凭据是否正确 if (username === 'admin' && password === 'password') { // 生成 JWT const token = jwt.sign({ username }, 'secret'); // 将 JWT 发送回客户端 return res.json({ token }); } // 如果凭据不正确,则返回错误信息 return res.status(401).json({ message: 'Invalid credentials' }); }); app.listen(3000, () => console.log('Server started on port 3000'));
在这个路由中,我们使用 jwt.sign
方法生成 JWT,并将它发送回客户端。注意,我们将密钥设置为 'secret'
,实际上应该将其替换为一个随机的、安全的字符串。
验证 JWT
现在,我们已经可以生成 JWT 并将其发送回客户端了。接下来,我们需要编写一个函数来验证 JWT 是否有效,以确保用户已经通过了身份认证,并有权访问受保护的资源。
以下是一个示例代码:
const express = require('express'); const jwt = require('jsonwebtoken'); const bodyParser = require('body-parser'); const app = express(); app.use(bodyParser.json()); // 这个变量用于存储需要进行身份认证的路由 const authRoutes = express.Router(); // 这个中间件用于验证 JWT 是否有效 authRoutes.use((req, res, next) => { // 从请求头中获取 JWT const token = req.headers.authorization?.split(' ')[1]; // 如果 JWT 不存在,则返回 401 错误 if (!token) { return res.status(401).json({ message: 'Authentication failed' }); } // 验证 JWT 是否有效 try { const decoded = jwt.verify(token, 'secret'); req.user = decoded; next(); } catch (error) { return res.status(401).json({ message: 'Authentication failed' }); } }); // 受保护的路由 authRoutes.get('/protected', (req, res) => { res.json({ message: `Welcome ${req.user.username}!` }); }); // 将路由添加到应用程序中 app.use('/', authRoutes); app.listen(3000, () => console.log('Server started on port 3000'));
在这个示例中,我们使用 jwt.verify
方法来验证 JWT 是否有效。如果 JWT 有效,则将解码后的数据放入 req.user
对象中,然后调用 next
函数继续处理请求。如果 JWT 无效,则返回 401 错误。
完整示例代码
以下是一个完整的示例代码:
const express = require('express'); const jwt = require('jsonwebtoken'); const bodyParser = require('body-parser'); const app = express(); app.use(bodyParser.json()); // 登录路由 app.post('/login', (req, res) => { // 获取用户提交的凭据 const { username, password } = req.body; // 验证凭据是否正确 if (username === 'admin' && password === 'password') { // 生成 JWT const token = jwt.sign({ username }, 'secret'); // 将 JWT 发送回客户端 return res.json({ token }); } // 如果凭据不正确,则返回错误信息 return res.status(401).json({ message: 'Invalid credentials' }); }); // 认证中间件 const authMiddleware = (req, res, next) => { // 从请求头中获取 JWT const token = req.headers.authorization?.split(' ')[1]; // 如果 JWT 不存在,则返回 401 错误 if (!token) { return res.status(401).json({ message: 'Authentication failed' }); } // 验证 JWT 是否有效 try { const decoded = jwt.verify(token, 'secret'); req.user = decoded; next(); } catch (error) { return res.status(401).json({ message: 'Authentication failed' }); } }; // 受保护的路由 app.get('/protected', authMiddleware, (req, res) => { res.json({ message: `Welcome ${req.user.username}!` }); }); app.listen(3000, () => console.log('Server started on port 3000'));
总结
在本文中,我们介绍了如何在 Express.js 中使用 JWT 进行身份认证。使用 JWT,我们可以解决传统的 Cookie/Session 身份认证方式所遇到的一些问题,例如跨域、扩展性和可伸缩性等。此外,JWT 还非常方便,可以轻松地序列化和传输数据。通过掌握本文中所介绍的知识,你将能够使用 JWT 来保护你的 Web 应用程序并提供更好的用户体验。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a0dcc0add4f0e0ff90e99f