JWT

JWT

  Json Web Token(JWT) 是个轻量级规范,允许用户和服务器之间传递安全可靠信息;

JWT构成

  JWT 实际是个字符串,由 header(头部), payload(载荷), signature(签名)组成;

header(头部)

  头部描述 JWT 最基本信息,例如类型和签名用的算法,比如

{"typ":"JWT","alg":"HS256"}

       以上头部 签名是HS256算法, base64加密

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

payload(载荷) 

  (1)标准中注册的声明(建议但不强制使用)

iss: jwt签发者
sub: jwt所面向的用户
aud: 接收jwt的一方
exp: jwt的过期时间,这个过期时间必须要大于签发时间
nbf: 定义在什么时间之前,该jwt都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

  (2)公共声明

  公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密. 

  (3)私有声明

 私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。
这个指的就是自定义的claim。比如下面面结构举例中的admin和name都属于自定的claim。这些claim跟JWT标准规定的claim区别在于:
JWT规定的claim,JWT的接收方在拿到JWT之后,都知道怎么对这些标准的claim进行验证(还不知道是否能够验证);
而private claims不会验证,除非明确告诉接收方要对这些claim进行验证以及规则才行。

      定义一个 payload

{"sub":"1234567890","name":"John Doe","admin":true}

      对其 base64 加密得到 jwt 第二部分

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

  

签证(signature)

  jwt 第三部分是一个签证信息,用于校验数据是否被篡改;

       由header(base64后的), payload(base64之后的), secret(盐) 三部分组成:

  这个部分需要base64加密后的header和base64加密后的payload使用 . 连接组成的字符串,然后通过 header 中声明的加密方式进行加盐 secret 组合加密,然后构成 jwt 第三部分。

TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

  将这三部分用.连接成一个完整的字符串,构成了最终的jwt:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

  注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。

  签名总结:Base64(头) + Base64(载荷) + 密钥(盐)  ---》加密 采用 头中指定的算法

  签名作用: 用于校验令牌 是否篡改

        令牌:

 

 

 

 

加密测试

    @Test
    public void testCreateToken(){
        JwtBuilder builder = Jwts.builder();
        builder.setIssuer("测试人");
        builder.setIssuedAt(new Date());
        builder.setSubject("令牌Test");
        builder.signWith(SignatureAlgorithm.HS256,"itCheck");
        System.out.println(builder.compact());
    }

输出

eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiLmtYvor5XkuroiLCJpYXQiOjE1OTc3MzM4MjUsInN1YiI6IuS7pOeJjFRlc3QifQ.Mjq7bFrsJELQBr0j5wYm4LoY3QiNerUMVJ5wDQKN590

 

解密测试

    @Test
    public void testCreateToken(){
        JwtBuilder builder = Jwts.builder();

        //构建令牌对象
        builder.setIssuer("测试人");
        builder.setIssuedAt(new Date());
        builder.setSubject("令牌Test");


        //添加载荷
        Map<String, Object> userInfo = new HashMap<String,Object>();
        userInfo.put("company","Baidu");
        userInfo.put("address","Shenzhen");
        builder.addClaims(userInfo); //添加载荷

        builder.signWith(SignatureAlgorithm.HS256,"itCheck");
        System.out.println(builder.compact());
    }

  

 

输出 

{iss=测试人, iat=1597733825, sub=令牌Test}

 

posted @ 2020-08-18 14:01  抽象Java  阅读(143)  评论(0编辑  收藏  举报