博学谷it学习技术支持
jwt是什么
JWT(JSON Web Token),本质就是一个字符串书写规范,如下图,作用是用来在用户和服务器之间传递安全可靠的信息。
主要用在前后端分离的项目中(还有服务器渲染的项目类型嘛),服务器当验证用户账号和密码正确的时候,给用户颁发一个令牌,这个令牌作为后续用户访问一些接口的凭证,后续访问会根据这个令牌判断用户时候有权限进行访问
主要组成
jwt分为三个部分:头部(Header)、载荷(Payload)、签名(Signature),并以.进行拼接。其中头部和载荷都是以JSON格式存放数据,只是进行了编码。\
头部(Header)
“typ”: “JWT”,
“alg”: “HS256”
}
有效载荷(Playload)
"role": [],
"iss": "baidu",
"exp": 1638841050,
"userName": "管理员",
"department": [],
"iat": 1638840690,
"userId": "1",
"account": "admin"
}
签名(Signature)
将Header和Playload拼接生成一个字符串str=“eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjpbXSwiaXNzI”, 使用HS256算法和我们提供的密钥(secret,服务器自己提供的一个字符串)对str进行加密生成最终的JWT, 即我们需要的令牌(token),形如:str.”签名字符串”。
认证流程
- 用户使用账号和密码发出post请求;
- 服务器使用私钥创建一个jwt;
- 服务器返回这个jwt给浏览器;
- 浏览器将该jwt串在请求头中像服务器发送请求;
- 服务器验证该jwt;
- 返回响应的资源给浏览器。
JWT 特点
- 体积小,因而传输速度快
- 传输方式多样,可以通过URL/POST参数/HTTP头部等方式传输
- 严格的结构化。它自身(在 payload 中)就包含了所有与用户相关的验证消息,如用户可访问路由、访问有效期等信息,服务器无需再去连接数据库验证信息的有效性,并且 payload 支持为你的应用而定制化。
- 支持跨域验证,可以应用于单点登录
在express中简单使用
const bodyParser = require("body-parser")
const jwt = require("./utils/jwt-simple")
// 这里由于简单实现,所以使用一个数组简单存取一下用户
const USER = [];
// JWT签名的密钥,这个是可以自定义的
const SECRET = "ChenSir#$_!"
let app = express();
app.use(bodyParser.json())
// 定义一个注册的接口, 大家不用深究具体的逻辑
app.post('/reg', function(req, res, next){
let user = req.body;
USER.push(user)
res.json({
code: 0,
msg: "ok"
})
})
// 定义登录接口
app.post("/login", function(req, res, next) {
let user = req.body;
let id = USER.findIndex(item => {
return item.username == user.username && item.password == user.password;
});
if(id != -1){
// 校验成功后使用jwt.encode()进行token获取, 需要传入payload和secret
let token = jwt.encode({
id,
username: user.username
}, SECRET)
res.json({
token
})
}else{
res.json({
code: -1,
msg: "上传信息有误"
})
}
})
// 获取信息接口,添加中间件进行权限校验
app.get("/info", function (req, res, next){
let authorization = req.headers["authorization"];
if(authorization){
let token = authorization.split(" ")[1];
try {
// 对token信息进行解码校验,使用jwt.decode()处理token解析出用户信息
let user = jwt.decode(token, SECRET)
req.user = user;
next(); // 成功取到用户
}catch(e){
res.status(401).send("Not Allowed");
}
}else{
res.status(401).send("Not Allowed");
}
}, function (req, res, next){
res.json(req.user)
})
app.listen(8080, function(){
console.log("server listening on 8080")
})
优缺点
优点:
json具有通用性,所以可以跨语言 组成简单,字节占用小,便于传输 服务端无需保存会话信息,很容易进行水平扩展 一处生成,多处使用,可以在分布式系统中,解决单点登录问题 可防护CSRF攻击
缺点:
payload部分仅仅是进行简单编码,所以只能用于存储逻辑必需的非敏感信息 需要保护好加密密钥,一旦泄露后果不堪设想 为避免token被劫持,最好使用https协议