之前在面试的时候被问到一个问题,Http怎么保持状态;其实当时的答案很简单,cookie或者session,这个大家都知道的,然后又问,如果客户端禁用cookie了哪?当时我想了一下,说使用jwt;个人是觉得这个没有问题的;所以简单记录下关于jwt的一些内容,文章分成几个部分,先简单介绍下http的状态保持,然后了解下jwt的理论知识,最后了解下应用方面;
1.禁用cookie的情况下保持登录状态
首先如何理解保持登录状态这个问题,其实保持登录状态就是服务端需要根据一些数据来识别发起请求的用户;最常用的是登录成功之后,服务端生成一个SessionID,然后设置到cookie,那么之后的所有请求都要带上cookie,服务端从header中取出session Id,再去查询用户的相关信息。所以保持登录状态的关键不是cookie,而是通过cookie保存和传输的session Id;
在禁用cookie的时候,可以使用jwt,返回access token,前端将它保存在local storage中,后续的请求,构造一个类似的Authorization: Bearer <access token>这样的请求头,服务器端从中取出token,之后进行解密payload部分,查询到用户id,最终实现的效果和cookie是一样的。
2.Jwt
Jwt由三部分组成,头部,载荷与签名;一个jwt的字符串的组成是 "头部.载荷.签名 "结构
1>头部Header
头部用于描述关于jwt的最基本的信息,例如类型以及签名使用的算法等,可以被弄成一个json对象。
{
"typ":"JWT",
"alg":"HS256"
}
这里alg是签名的算法使用的是HS256;然后对header部分进行Base64编码,之后的字符串就形成了JWT的Header部分
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
2>Payload(载荷)
载荷部分主要承载的是我们存储的内容,比如用户的id等信息;
{
"iss":"John Wu JWT",
"iat":1441593502,
"exp":1441594722,
"aud":"www.example.com",
"sub":"jrocket@example.com",
"from_user":"B",
"target_user":"A"
}
这里的前五个字段是由jwt的标准定义的。
iss: 该JWT的签发者
sub: 该JWT所面向的用户
aud: 接收该JWT的一方
exp(expires): 什么时候过期,这里是一个Unix时间戳
iat(issued at): 在什么时候签发的
将上面的json对象进行base64编码之后可以得到下面的字符串,这个字符串就是载荷(Payload)
eyJpc3MiOiJKb2huIFd1IEpXVCIsImlhdCI6MTQ0MTU5MzUwMiwiZXhwIjoxNDQxNTk0NzIyLCJhdWQiOiJ3d3cuZXhhbXBsZS5jb20iLCJzdWIiOiJqcm9ja2V0QGV4YW1wbGUuY29tIiwiZnJvbV91c2VyIjoiQiIsInRhcmdldF91c2VyIjoiQSJ9
3>签名
签名是将header和Payload拼接在一起之后进行HS256算法进行加密生成的字符串,在加密的时候,需要提供一个密钥secret,比如使用“mystar”作为密钥,加密之后的内容
rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
最后将签名也拼接在字符串的后面,就得到了完整的Jwt
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
几个问题需要说明下:
1>Base 64编码是可逆的,所以payLoad中一定不要存放敏感信息,比如用户的密码啥的,一般存放userId,login和用户的角色都是可以的;
2>签名的目的是啥,目的是防止payLoad被篡改,如果被篡改了,那么header + payload 的HS256加密的结果和签名肯定不相等,说明这个token被动过了,应该拒绝这个token,所以这里的HS256密钥不能泄露出去;
3.jwt和session区别
jwt可以来做单点登录,Payload中存储userId信息和Session的最大区别是Session要占用大量的服务器内存,对于大型的应用来说可能要保存很多状态,而jwt将用户状态分散到客户端中,明显减少了服务器的内存压力;虽说jwt方式可以让服务器有一些计算压力,但是还是可以的;jwt相比cookie session来说,主要解决的是服务器端的session问题,将服务器的session存储在用户端;
参考资料
https://blog.csdn.net/sxdtzhaoxinguo/article/details/77965226
http://blog.rainy.im/2015/06/10/react-jwt-pretty-good-practice/