通常状况下,客户的会话数据会存在文件中,或者引入redis来存储,实现session的管理,可是这样操做会存在一些问题,使用文件来存储的时候,在多台机器上,比较难实现共享,使用redis来存储的时候,则须要引入多一个集群,这样会增长管理的工做量,也不方便。有一个直观的办法,就是将session数据,存储在客户端中,使用签名校验数据是否有篡改,客户请求的时候,把session数据带上,获取里面的数据,经过校验,而后进行身份认证。html
数据存储在客户端中,会存在一些挑战:web
为了实现客户端存储会话数据的解决方案,制定了JSON Web Token的协议,详细的协议能够在:RFC7529查看。下面咱们看看jwt协议是怎样解决上面的挑战的。redis
JWT加密后,使用的格式,分为三部分,header,payload和signature,使用.号链接起来:算法
Header.Payload.Signature
JWT的header,定义了存储的算法和协议名称:json
{ "alg": "HS256", "typ": "JWT" }
下面这些负载字段,是JWT协议提供选用,通常状况下,payload的数据是不加密存储在客户端中的,因此要注意不要存储敏感信息:安全
iss (issuer):签发人 exp (expiration time):过时时间 sub (subject):主题 aud (audience):受众 nbf (Not Before):生效时间 iat (Issued At):签发时间 jti (JWT ID):编号
payload除了这些字段,还能够扩展一些数据,更加符合咱们的需求:服务器
{ "iss": "foo", "extend_data": "hell" }
服务端,有一个秘钥,经过秘钥对header和payload进行签名,使用header中指定的签名算法类型,通常有HMAC,RSA和ECDSA,下面是签名的格式:session
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
JWT通常会将token数据存储在http请求的header中,经过Bearer来分隔:数据结构
headers: { 'Authorization': 'Bearer ' + token }
定义好数据结构和通信方式,下面看看如何处理一些问题:加密
每个token产生,都应该限制好过时时间,确保只能在一段时间内有效,保证安全。当达到过时时间时,须要对token进行续签,能够定时想服务器提交请求,从新获取token来实现。
当客户登陆的时候,须要注销登陆会话,因为token是没有状态的,只能在客户端把token删除,伪造一个注销的状态,真正的注销只能等待token过时。
也能够有种办法,就是把token的信息记录在redis中,当客户退出时,讲redis中的token删除,而通常请求时,会经过redis对数据进行校验,这样能够实现真的注销效果,但要引入多一个组件,把token变为有状态,若是用这种办法,也就不符合token存储在客户端的模式了
若是可以支持,会话用的数据量较小,对注销能够等待超时的长效的场景,使用jwt做为会话数据存储是会比较方便的。而对于会话数据量大的场景,仍是使用通常的方式比较好点。