深圳市龙岗区网站建设,推广手段和渠道有哪些,做旅游业务的商业网站,平台型网站如何推广在现代web应用中#xff0c;用户身份认证是非常重要且必不可少的一环。而使用Node.js和Express框架#xff0c;可以方便地实现用户身份认证。而在这个过程中#xff0c;jsonwebtoken这个基于JWT协议的模块可以帮助我们实现安全且可靠的身份认证机制#xff0c;可以让我们轻…在现代web应用中用户身份认证是非常重要且必不可少的一环。而使用Node.js和Express框架可以方便地实现用户身份认证。而在这个过程中jsonwebtoken这个基于JWT协议的模块可以帮助我们实现安全且可靠的身份认证机制可以让我们轻松地生成、解析和验证JWT。本文主要介绍如何在Node.js的Express框架中使用jsonwebtoken模块来实现用户身份认证。
一、什么是jwt
jwt介绍https://restfulapi.cn/jwt
JWTJSON Web Token是一种基于JSON的开放标准用于在网络上以安全方式传输声明。JWT通常用于身份验证和授权。它是一种可自包含的身份认证机制由三部分组成头部、载荷和签名。JWT的头部和载荷都是使用Base64编码后的JSON字符串签名是由头部和载荷使用密钥进行哈希计算得到的字符串。JWT可以在客户端和服务器之间传输并且可以在传输过程中防止数据被篡改。由于它是无状态的因此可以简化Web应用程序的开发和维护。
二、jsonwebtoken基本使用
jsonwebtoken是一个Node.js库用于创建、解码和验证JWT令牌(JSON Web Tokens)。在Web应用中这些令牌通常用于身份验证和授权。
以下是如何在Node.js应用中使用jsonwebtoken的基本步骤。
1. 安装jsonwebtoken
首先你需要使用npm或yarn将jsonwebtoken包添加到你的项目中
npm install jsonwebtoken --save或者
yarn add jsonwebtoken2. 导入使用
然后在你的代码中导入jsonwebtoken
const jwt require(jsonwebtoken);3. 创建token
创建一个令牌
let token jwt.sign({ foo: bar }, shhhhh);在上面的代码中我们使用jwt.sign方法创建了一个新的令牌。 这个方法需要两个参数
一个包含你的payload的对象这个对象中的数据会被编码到生成的令牌中比如userInfo用来签名令牌的秘密字符串。
4. 验证token
验证一个令牌
jwt.verify(token, shhhhh, (err, decoded) {if (err) {// 处理错误} else {// 使用解码后的令牌数据}
});使用jwt.verify方法可以解码并验证一个令牌。
该方法需要三个参数
解码的令牌用于签名的相同的秘密字符串操作完成时被调用的回调函数。
注意 所有的令牌都应该只通过HTTPS发送以防止被拦截。 秘密字符串应该在你的应用中保持私密不能让其他人知道。 任何存储在令牌中的信息都可以被任何拥有秘密的人解码。因此你永远不应该在令牌中存储敏感信息如密码或银行账户信息。
三、在express中应用示例
在实际项目中我们可以使用jsonwebtoken模块来实现身份认证。jsonwebtoken是基于JSON Web TokensJWT协议的实现模块可以用于生成、解析和验证JWT。JWT是一种基于JSON的开放标准RFC 7519用于在网络上安全地传输声明。
以下是一个使用express和jsonwebtoken实现身份认证的示例
const express require(express);
const jwt require(jsonwebtoken);const app express();// 定义一个中间件函数用于身份认证
function verifyToken(req, res, next) {// 从请求头中获取tokenconst token req.headers[authorization];if (!token) {return res.status(401).send({auth: false,message: No token provided.});}// 验证token是否有效jwt.verify(token, process.env.SECRET_KEY, (err, decoded) {if (err) {return res.status(500).send({auth: false,message: Failed to authenticate token.});}// 将解码的用户信息存储到请求对象中req.userId decoded.id;next();});
}// 定义一个路由需要身份认证
app.get(/api/protected, verifyToken, (req, res, next) {// 返回受保护的数据res.status(200).send({message: Access granted.});
});// 定义一个路由用于登录返回token
app.post(/api/login, (req, res, next) {// 从数据库中获取用户信息const user { id: 123 };// 生成tokenconst token jwt.sign({ id: user.id }, process.env.SECRET_KEY, {expiresIn: 60 * 60 // token有效期为1小时});// 返回tokenres.status(200).send({auth: true,token: token});
});// 启动服务器监听端口
app.listen(3000, () {console.log(Server started on port 3000);
});在上述示例中我们定义了一个中间件函数verifyToken用于身份认证。该函数从请求头中获取token并通过jsonwebtoken的verify方法验证token是否有效。如果验证通过则将用户信息存储到请求对象中以便后续路由函数使用。
我们还定义了两个路由函数/api/protected和/api/login。/api/protected需要身份认证才能访问而/api/login用于登录并返回生成的token。
在实际项目中我们应该将SECRET_KEY等敏感信息放在环境变量中以提高安全性。此外我们还可以使用jsonwebtoken提供的其他功能如验证token的签名算法、payload和header等信息。
四、jwt逻辑抽离
在上面的示例中我们用jwt实现了身份认证但是这只是在一个接口中认证如果接口多了呢每次都要将这个认证的中间件加上吗这样先不说开发实现的累不累冗余不单从维护层面来讲也是很不合理。所以我们应该将认证的逻辑抽离出来以便于接口调用和维护。具体步骤如下
1. 新建jwt.js文件
这个文件中就封装三个函数
token的生成token的认证排除哪些接口不需要认证就可以访问比如/login,
// jwt.js
const jwt require(jsonwebtoken);
const { promisify } require(util);
const { uuid } require(../config/config.default);
const tojwt promisify(jwt.sign);
const verfiy promisify(jwt.verify);// 生成token
module.exports.createToken async (userinfo) {var token await tojwt({ userinfo }, uuid, {expiresIn: 60 * 60 * 24,});return token;
};// jwt认证的中间件
const jwtAuthMiddleware async (req, res, next) {var token req.headers.authorization;token token ? token.split(Bearer )[1] : null;if (!token) {return res.status(402).json({ error: 请传入token });}if (token) {try {let userinfo await verfiy(token, uuid);req.user userinfo;next();} catch (error) {res.status(402).json({ error: 无效的token });}} else {next();}
};// 承认的url排除列表
const jwtAuthExcluedList [/api/login, /api/register];
// 检查排除列表的中间件
module.exports.jwtAuthExclued (req, res, next) {// 检查请求 URL 是否在排除 jwtAuth 的列表里面if (jwtAuthExcluedList.includes(req.path)){next(); // 在列表里跳过后续中间件} else { jwtAuthMiddleware(req, res, next); // 不在列表里就调用jwt中间件进行身份认证}
};
这样封装以后我们只需要在访问路由之前添加使用jwtAuthExclued 的中间件就可以实现对接口的token认证在login接口中调用createToken生成token可以了。
2. 在登录接口中生成token
比如
loginController
// login
// 用户登录
exports.login async (req, res) {// 客户端数据验证// 链接数据库查询var dbBack await User.findOne(req.body)if (!dbBack) {return res.status(402).json({ error: 邮箱或者密码不正确 })}dbBack dbBack.toJSON()dbBack.token await createToken(dbBack)res.status(200).json(dbBack)
}3. 添加全局认证中间件
app.js
const express require(express);
const app express();
const { jwtAuthExclued } require(./util/jwt);
const router require(./router);// 添加排除jwt中间件
app.use(jwtAuthExclued);
// 添加路由中间件
app.use(/api, router);五、jwt和session对比
下面是JWT和Session的对比表格
对比因素JWTSession存储存储在客户端不需要服务器保持会话状态。存储在服务器需要服务器维护会话信息。安全性加密较严密但如果token被窃取攻击者可以任意使用。如果sessionID被窃取攻击者可以冒充用户登陆。性能在每次请求时需要验证和解码token性能较差。只需查找sessionID就能获取会话信息性能较好。扩展性在多服务器或者跨域环境中更易扩展。在多服务器环境中需要同步session扩展性较差。数据大小JWT的大小比sessionID大因此需要更多的带宽。sessionID大小稳定对带宽需求较小。到期时间可以为每个token设置不同的过期时间。所有session的过期时间通常相同。客户端存储位置可以存储在Cookie, LocalStorage, SessionStorage中存储在Cookie中。跨域问题无跨域问题且对于移动应用而言友好。跨域问题复杂需要服务器支持CORS。状态无状态服务器不需要保存用户信息。有状态服务器需要保存用户信息。使用场景用于认证和信息交换尤其适合单页应用(SPA)和前后端分离的项目主要用于记录用户状态适配传统的后端渲染的Web服务
总体上来说JWT适用于前后端分离的API服务它可以简化服务端的存储需求并提供更好的跨平台兼容性和可扩展性同时也能提供安全可靠的身份认证机制。而Session则适用于服务器渲染的Web应用它可以提供更高的安全性和可调用性同时也能减轻客户端的流量负担。不同的场景需要选择最适合的身份认证方案根据实际需求进行选择。
六、总结
在本文中我们探讨了如何在Node.js的Express框架中使用jsonwebtoken来实现身份认证。我们首先介绍了JWT协议和jsonwebtoken模块的基础知识然后展示了如何在Express中使用jsonwebtoken来生成、解析和验证JWT。通过在实际项目中的举例我们演示了如何将jsonwebtoken与路由中间件结合使用实现基于token的用户身份认证机制。使用jsonwebtoken可以为我们的web应用提供更安全和可靠的用户身份认证方案同时jwt的优点也是很明显的无需在服务端保存session信息具有可扩展性和跨平台兼容性等特点。通过本文的介绍相信读者已经能够掌握jsonwebtoken的基本使用方法和原理能够在实际项目中使用jsonwebtoken实现安全可靠的身份认证机制。