JWT认证流程
跨域认证解决方案,JWT的流程为:
- 客户端发送账号和密码请求
- 服务端收到请求,验证用户名密码是否通过
- 验证成功后,服务端会生成唯一的token,将其返回给客户端
- 客户端收到token,会将其存储在cookie或者localStorage中
- 之后每一次客户端向服务端发送请求,都会通过cookie 或者header携带该token
- 服务端验证token的有效性,通过后才返回响应的数据
token 认证优点 - 支持跨域访问: cookie不允许跨域访问,
- . 无状态: token机制在服务端不需要存储session信息, token包含了所有登录用户的信息,在客户端的cookie活本地存储状态信息
- 适用性更广: http协议的客户端,都可以使用token认证
10.不需要考虑csrf: 不再依赖cookie, 所以token不会发生csrf,无需考虑csrf防御
JWT结构:
一个jwt是一个字符串, 它由三部分组成: 头部、载荷、签名,中间用.分开。
头部/header
header由两部分组成: token的类型 jwt 和算法名称: HMAC、SHA256、RSA
{
"alg": "HS256",
"type": "JWT"
}
载荷 / Payload
Payload 是一个JSON对象,存放传递的数据。JWT有七个字段
1. iss: 发行人
2. exp: 到期时间
3. sub: 主题
4. aud: 用户
5. nbf: 在此之前不可用
6. iat: 发布时间
7. jti: JWT ID
除了默认的七个字段,还可以添加自己想要的任何字段。
payload: 存放用户登录成功后的信息
{
"iss": "xxx",
"sub": "xxx",
"aud": "xxx",
"user": [
"userName": 'admin',
'gender': 1,
'nickname': 'a'
]}
签名/ signature
签名部分 对头部、载荷两部分数据进行的数据签名
为了保证不被篡改、要有一个密钥存放在服务端
生成签名的代码:
String signature = HMACSHA256(base64UrlEncode(header) + '.' + base64urlEncode(payload), secret)
JWT 基本使用
客户端收到服务端返回的JWT, 可以存储在Cookie里面,也可以存储在localStorage
客户端每次与服务器通信,都要带上JWT
把JWT保存在cookie里面发送请求, 不能跨域
放在http请求的头信息authrization字段
fetch('license/login', {
headers: {
'Authorization': 'X-TOKEN' + token
}
})
代码实现
var token = jwt.sign({
exp: Math.floor(Date.now() / 1000) + 60*60*24, // 设置JWT的过期时间为当前时间加一天
name: data.person, // 设置JWT中的name字段为data.person的值
}, config.secret, function(err, token) { // 使用config.secret作为密钥对JWT进行签名
res.json({ // 返回一个JSON响应
msg: { // 响应中的msg字段
status: 1, // 设置状态为1
msg: "登录成功" // 设置消息为"登录成功"
},
data: { // 响应中的data字段
token: token // 将生成的JWT作为token字段的值
}
})
})
// 验证jwt
new Promise(function(resolve, reject) {
jwt.verify(token, config.secret, function(err, decoded) { // 使用config.secret对JWT进行验证
if (err) { // 如果验证出错
res.json({ // 返回一个JSON响应
ok: 0, // 设置ok字段为0,表示验证失败
msg: err // 设置msg字段为错误信息
})
} else { // 如果验证成功
// 在这里可以对验证成功后的逻辑进行处理
}
})
})