jwt 了解
原session/cookie结构
用户一般做用户认证流程:
- 用户向服务器发送密码和用户名,在使用https之前,如果不做加密则是明文传输。
- 服务器向数据库验证密码是否一致,如一致,返回token,并将用户登录信息和token写入session
- 客户端拿到token,将token写入cookie,每次请求都发送token
- 服务器验证token正确性
这样就拓展性不怎么好,在集群或跨域时,不同服务器怎么共享session,当然可以将session存入数据库或其他的持久的地方,每次向持久层请求数据就好,但是工程量大,如果持久层挂了,认证就会失败。
jwt解决方案
个人理解:
- 服务器根本不保存会话数据,而是在登录验证后,将用户登录信息生成一个json字符串,然后用特有的密钥生成签名以防止数据被篡改,然后处理生成jwt token发给客户端,然后客户端每次请求把jwt token发给服务器,服务器仅依靠这个token来识别用户。
jwt组成
jwt token分为三个部分:Header、Payload、Signature
-
Header:一个json对象,用来描述jwt本身,通常包含两个属性,alg和typ,然后将这个对象用Base64URL转为字符串
- alg:algorithm,签名的算法,默认为 HMAC SHA256(写成 HS256)。
- typ:type,该令牌的类型,这里使用jwt,所以令牌是jwt。
-
Payload:json对象,用于存放实际需要传递的内容,如签发人、过期时间等等
- jwt官方定义了七个字段:
- iss (issuer):签发人
- exp (expiration time):过期时间
- sub (subject):主题
- aud (audience):受众
- nbf (Not Before):生效时间
- iat (Issued At):签发时间
- jti (JWT ID):编号
- 当然这个区域还可以定义私有字段
- 由于jwt本身默认不加密,所以任何人都可以读到,敏感信息还是别放这里了
- 这一部分也要用Base64URL转为字符串
- jwt官方定义了七个字段:
-
Signature:如果直接将Header、Payload传给服务器,那么服务器就无法得知这个东西是否被更改过。所以需要一个签名。
-
签名的方法就是将Header和Payload用一个密钥(secret)使用Header中指定的签名算法加密生成签名
-
签名的公式如下(使用默认HMASCSHA256)
-
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
-
-
生成签名后,把Header、Payload、Signature拼接成为一个字符串,每个部分用” . “ 分隔,就生成一个jwt token,就可以返回给客户端
-
服务端每次拿到token后,为验证是否正确,可以将Header、Payload部分再次加密为Signature,和客户端传过来的做对比,如果不一样,就证明被篡改。
优缺点
优点
- 服务器不再保存会话信息,对持久层依赖减少
缺点
- 由于服务器不再保存会话信息,所以除非做其他逻辑设置,那么在jwt到期之前它都会有有效
- jwt本身包含认证信息,一旦泄露,任何人都可以获得这个令牌的所有权限,所以应该将jwt有效期设置比较短
- 由于http协议是明文,所以要么加密,要么用https传输以减少盗用。
后记
idea挂了,不得已用vim改了一下代码,发现简直被idea惯坏了。。。
-
注意:本文归作者所有,未经作者允许,不得转载