写在前面:
我是「沸羊羊_」,昵称来自于姓名的缩写 fyy ,之前呕心沥血经营的博客因手残意外注销,现经营此账号。
本人是个小菜,正向着全栈工程师的方向努力着,文章可能并不高产,也很基础,但每写一篇都在用心总结,请大佬勿喷。
如果您对编程有兴趣,请关注我的动态,一起学习研究。
感谢每位读者!
传统的 session 认证
session
http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证,那么下一次请求时,用户还要再一次进行用户认证才行,因为根据http协议,我们并不能知道是哪个用户发出的请求,所以为了让我们的应用能识别是哪个用户发出的请求,我们只能在服务器存储一份用户登录的信息,这份登录信息会在响应时传递给浏览器,告诉其保存为cookie,以便下次请求时发送给我们的应用,这样我们的应用就能识别请求来自哪个用户了,这就是传统的基于session认证。
基于session认证暴露的问题
1、内存开销大
每个用户经过我们的应用认证之后,我们的应用都要在服务端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大。
2、扩展性不强
用户认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应的限制了负载均衡器的能力。这也意味着限制了应用的扩展能力。
3、CSRF
跨站请求伪造,因为是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击
token
token校验过程
- 用户第一次登录时,服务端生成Token并返回给客户端,保存在客户端的 localStorage
- 以后再访问时,需要携带token,将携带的token和在服务端保存的 token 信息进行比对校验
token缺陷
客户端每次登录时,依然需要访问数据库进行查询,并没有减轻对数据库的访问压力
什么是JWT
JWT(Json Web Token)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
JWT的使用场景
场景一
Authorization (授权) : 这是使用JWT的最常见场景。一旦用户登录,后续每个请求都将包含JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录是现在广泛使用的JWT的一个特性,因为它的开销很小,并且可以轻松地跨域使用。
场景二
Information Exchange (信息交换) : 对于安全的在各方之间传输信息而言,JSON Web Tokens无疑是一种很好的方式。因为JWT可以被签名,例如,用公钥/私钥对,你可以确定发送人就是它们所说的那个人。另外,由于签名是使用头和有效负载计算的,您还可以验证内容没有被篡改。
JWT实现过程
token结构
token 由三段字符串组成,并且用 . 连接起来。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
- 第1段:header(头部),内部包含算法/token类型
{ "alg": "HS256", "typ": "JWT" }
将此json转化为字符串,然后做 base64url 加密
- 第2段:payload(载荷),自定义值
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 #超时时间 }
将json转化为字符串,做base64url 加密
- 第3段:signature(签证)
- 将第1、2段的密文拼接起来
- 对拼接的密文进行 HS256加密 + 加盐
- 对 HS256 加密的密文再做 base64url 加密
token传递过程
- 用户第一次登录成功后,使用 jwt 创建一个 token,并给用户返回,保存在客户端的 localStorage 中
- 以后用户再次访问时,需要携带 token,服务端获取token后,再做 token 的校验(服务端不存储token)
token校验过程
- 服务端获取token后,对token进行切割,切割为三部分
- 对第二段密文进行 base64url 解密为明文,并获取 payload 信息,检测 token 是否已经超时?
- 把第1、2段密文拼接,再次执行 HS256 加密,将加密后的密文 与 使用 base64url 解密后的第3段密文进行比较,如相等,则 token 未被修改过(认证通过)
JWT优势?
- JWT是可以进行跨语言支持的,JAVA,JS,NodeJS,PHP等很多语言都可以使用
- 因为有了 payload 部分,JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息
- 便于传输,JWT构成简单,字节占用小,所以是非常便于传输的
- 不需要在服务端保存会话信息,所以它易于应用的扩展