jwt 了解

jwt 了解

原session/cookie结构

用户一般做用户认证流程:

  1. 用户向服务器发送密码和用户名,在使用https之前,如果不做加密则是明文传输。
  2. 服务器向数据库验证密码是否一致,如一致,返回token,并将用户登录信息和token写入session
  3. 客户端拿到token,将token写入cookie,每次请求都发送token
  4. 服务器验证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转为字符串
  • 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惯坏了。。。


已有 0 条评论

    欢迎您,新朋友,感谢参与互动!