前言
目前web开发前后端已经算非常的普及了。前后端分离要求我们对用户会话状态要进行一个无状态处理。我们都知道通常管理用户会话是session。用户每次从服务器认证成功后,服务器会发送一个sessionid给用户,session是保存在服务端 的,服务器通过session辨别用户,然后做权限认证等。那如何才知道用户的session是哪个?这时候cookie就出场了,浏览器第一次与服务器建立连接的时候,服务器会生成一个sessionid返回浏览器,浏览器把这个sessionid存储到cookie当中,以后每次发起请求都会在请求头cookie中带上这个sessionid信息,所以服务器就是根据这个sessionid作为索引获取到具体session。
痛点
上面的场景会有一个痛点。对于前后端分离来说。比如前端都是部署在一台服务器的nginx上,后端部署在另一台服务器的web容器上。甚至 前端不能直接访问后端,中间还加了一层代理层。
大概如下所示:
也就是说前后端分离在应用解耦后增加了部署的复杂性。通常用户一次请求就要转发多次。如果用session 每次携带sessionid 到服务器,服务器还要查询用户信息。同时如果用户很多。这些信息存储在服务器内存中,给服务器增加负担。还有就是CSRF(跨站伪造请求***)***,session是基于cookie进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的***。还有就是sessionid就是一个特征值,表达的信息不够丰富。不容易扩展。而且如果你后端应用是多节点部署。那么就需要实现session共享机制。不方便集群应用。
什么是JWT
所以JSON WEB TOKEN(以下称JWT)可以解决上面的问题。JWT还是一种token。token 是服务器颁发给客户端的。就像户籍管理部门给你发的身份证一样。你拿着这个证件就能去其他部门办事。其他部门验证你这个身份证是否过期,是否真假。不用每次都让户籍来认可。同时token 天然防止CSRF***。而且JWT可以携带一些不敏感的用户信息。这样服务器不用每次都去查询用户信息。开箱即用,方便服务器处理鉴权逻辑。
是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519)。该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。
JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
JWT的特点:
- 简洁(Compact): 可以通过URL,POST参数或者在HTTP header发送,因为数据量小,传输速度也很快
- 自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库或 缓存
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
JWT消息结构:
JWT有3个组成部分,分别是
- 头部(header) 声明类型以及加密算法 如 {"alg":"HS256","typ":"JWT"} 用Base64进行了处理
- 载荷(payload) 携带一些用户身份信息,用户id,颁发机构,颁发时间,过期时间等。用Base64进行了处理。这一段其实是明文,所以一定不要放敏感信息。
- 签证(signature) 签名信息,使用了自定义的一个密钥然后加密后的结果,目的就是为了保证签名的信息没有被别人改过,这个一般是让服务器验证的。
从上面的例子可以看出来JWT的规则是这样的 <header>.<payload>.<signature>三部分通过"."进行拼接 。JWT.io提供解析的方法 我们可以拿上面那个token去玩一玩
所以JWT不是简单的token,比session+cookie机制更加丰富。应用场景更加丰富。
JWT不足之处:
JWT并不是完美的。
- 比如说有可能一个用户同时出现两个可用的token情况。
- 还有如果失效过期了如何进行续期的问题。
- 同样会出现token被盗用的问题。
- 注销如何让token失效的问题。
- 用户信息修改让token同步的问题。
本文简单说明了一下JWT,为了避免篇幅过长会在下一篇将对上面JWT这些缺陷进行实际解决方案的解读。