Json Web Token在前后端实践思考分析
什么是Json Web Token(JWT)
JSON Web Token(JWT)是一种用于在两个实体之间安全传输消息的开放标准(RFC 7519)。JWT以JSON格式编码数据,可以安全地存储在URL参数、POST参数、HTTP标头或Cookie中。JWT包括三个部分:头部,载荷和签名,最终生成的JWT字符串通常具有三段式的形式 xxx.yyy.zzz。其中XXX表示这个头部,YYY表示这个载荷,而ZZZ则表示签名。
JWT的使用场景
JWT通常用于Web应用程序和API接口的设计中,用于身份验证和授权。 在用户成功登录后,JWT会生成并发送到客户端,客户端可以将JWT存储在Cookie或localStorage中,并在每次向服务器发送请求时将JWT包含在请求头或其他需要的地方。 服务器在接收到请求时,会验证JWT是否合法并取出其中的信息,以确定用户是否可以访问被请求的资源。
JWT的优缺点
优点
- 减轻服务器压力:JWT自包含,自描述,可以包含用户身份信息,减少服务器查询DB的次数。
- 跨域传输:JWT 在预设的几个重要参数中没有存储服务端的IP和端口,可随意在各个服务间流通传递。
- 安全性好:JWT 中包含了签名信息,保证了传输过程中信息的不被篡改和窃听。
缺点
- 可以被窃取:如果JWT被不法分子拦截,那么该分子拥有的就是这个用户的全部身份信息了。
- JWT中的算法可能会引起安全性问题: 目前 JWT 中使用最多的几个算法就是 HMAC SHA256 和 RS256,使用不当,轻则会导致 JWT 被轻易破解,严重的话还会影响服务端的安全性。
JWT的实现思路
在实际应用中,JWT的应用通常会按照以下流程进行:
- 用户使用用户名密码登录
- 服务器验证用户名密码,生成JWT并返回到客户端
- 客户端将JWT存储在Cookie或localStorage中
- 在每次向服务器发送请求时,客户端将JWT包含在请求头或其他需要身份验证的地方
- 服务器通过验证JWT的签名和有效期,取出其中的信息并判断用户是否有权限访问被请求的资源
下面,我们详细介绍如何在前后端中使用JWT。
在前端中使用JWT
生成JWT
前端生成JWT一般使用 JS库 jsonwebtoken 。示例代码如下所示:
const jwt = require('jsonwebtoken');
const secret = 'my_secret_key'; // 这个 key 不能被泄露出去
const payload = { username: 'admin' }; // 载荷,通常存储用户信息
const token = jwt.sign(payload, secret, { expiresIn: '1h' }); // 签发 JWT,设置过期时间为 1 小时
console.log(token); // 输出 JWT 字符串
存储JWT
前端可以将JWT【存储在Cookie中】或【存储在LocalStorage中】。这里以LocalStorage为例:
localStorage.setItem('my_token', token);
在每次请求中发送JWT
前端可以通过请求头的方式将JWT发送到服务器上。示例代码如下所示:
const xhr = new XMLHttpRequest();
xhr.open('GET', '/api/user');
xhr.setRequestHeader('Authorization', `Bearer ${localStorage.getItem('my_token')}`);
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
}
};
xhr.send();
在后端中使用JWT
验证JWT
服务器端通常会使用 Node.js】中间件库 express-jwt 验证JWT的有效性,示例代码如下所示:
const express = require('express');
const jwt = require('express-jwt');
const app = express();
const secret = 'my_secret_key';
app.use(
jwt({
secret,
algorithms: ['HS256'],
}).unless({
path: ['/login'],
})
);
app.get('/api/user', (req, res) => {
console.log(req.user.username); // 输出用户名信息
res.send(req.user);
});
app.listen(3000, () => {
console.log('Server start at http://localhost:3000');
});
在上述代码中, jwt()
从请求中解析出JWT,然后验证签名的有效性,如果JWT验证通过,解码后的用户信息就被附加到请求的 req.user
属性中,下面路由中就可以使用 req.user
来访问用户的信息了。
生成JWT
服务器端生成JWT也可以使用上述 jsonwebtoken 库的 sign()
调用,示例代码如下所示:
const jwt = require('jsonwebtoken');
const secret = 'my_secret_key';
const payload = { username: 'admin' };
const token = jwt.sign(payload, secret, { expiresIn: '1h' });
res.send({ token });
总结
以上是JWT在前后端分别的实践思考分析。使用JWT可以有效地解决跨域通信问题,并提升数据安全性。当然,针对JWT本身的安全威胁,我们需要在使用前详尽地评估其是否合适自己的应用场景,严格按照规范调用API。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Json Web Token在前后端实践思考分析 - Python技术站