昨天一同学问我用token还是session好,我说是没什么区别。于是今天又回头理了一遍JWT(json web token),总算是理解了JWT的意义。
先说说前端部分,前端部分不管后台用的什么,没什么区别,就是把后台返回的登录标识存到本地,然后每次请求携带传给后台,不管是通过cookie还是header里面加token,都是全局配置,所以对前端来说两者没什么区别。
如果后台是通过session,一般服务器会对登录请求保存相关数据到session里面,然后给用户返回一个sessionid写入用户的cookie,之后用户每次请求都会携带cookie,服务器通过这个id获取用户信息。有说这个方法服务器要存储session,占内存,说每次携带浪费带宽,我觉得这两个都不是问题,一般前端使用其他方法也是全局配置,都会携带认证标识,至于服务器占内存,这点内存应该也可以忽略不计。
使用session这种方法,最主要的应该是对服务器集群和跨域服务的架构影响很大,因为cookie是不支持跨越的,如果是集群,就要共享session数据,让每台服务器都能读取session。当然,如果是单个服务器的,那就什么问题没有。
为了解决session的这个问题,使用JWT就能完美解决。简单说JWT就是把用户信息变成base64加上签名返回给前端,由前端存储,每次请求携带上,后台再通过签名判断是否经过篡改,如果是正确的,直接使用用户信息。这样,服务器就不需要存储session了,不管是跨域的还是集群的,就都能获取用户信息。
JWT三部分:
Header头部:{"alg": "HS256","typ": "JWT"},alg是签名算法,默认是HS256,typ是token类型,一般JWT默认为JWT。
Payload存放需要传递的数据,JWT规定了7个官方字段:
iss(issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
这是官方规定的,你可以自己随意加字段,比如id之类的。
Singnature签名,对前两个部分签名,防止篡改。就是公钥密钥一样,密钥只有服务器知道,不能让客户端知道。接着就是转换成base64,中间用.隔开拼接成一个字符串,返回给前端。
当前端收到这个令牌之后,存cookie还是localstorage都可以,要注意的就是cookie不能跨域,所以很多是存在localstorage,然后header里面加个字段发送给后台。后台收到后通过Header和Payload进行签名跟发给后台的签名对比,看是否被篡改。
这边只是介绍了JWT大概的原理,至于怎么签名防止篡改就不去研究了。但是一定要注意,转化成base64是没有加密的,除非你生成之后自己去加密,所以不能把一些敏感数据放到JWT。JWT只是解决用户会话问题。就像使用sessionid标识服务器的session一样,这个sessionid是没有什么加密的。
JWT的缺点就是不能随时废除这个签名,在到期之前都有效,不过服务器可以做一些逻辑去解决这个问题。
至于怎么解决加密的安全性问题,后台技术应该很成熟了,这边还是要最后强调一下,JWT本身只是解决用户会话问题,本身没有任何加密性,加密的机制后台要通过另外的方法去实现。
(完)
Coding 个人笔记