spring cloud学习笔记 JWT令牌

  在微服务框架中,用户信息是个很头疼的问题。首先为了实现单点登录,用户在一个系统登录后,就无需在其他系统再进行登录,那么用户信息就需要在第一次登录后进行存储到cookie,那么当我们在cookie中获取用户信息时,该如何验证用户信息没有被篡改?其次用户信息都是敏感数据,如果明文展示势必会造成隐私泄露。为了解决这些问题,就有必要学习JWT令牌。

一、JWT介绍

   JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。JWT一共有三部分组成,分别是:头部、载荷、签证。

1.头部(Header) 

  头部用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。它是一个JSON字符串,如下例子:

{
    "typ":"JWT",//类型
    "alg":"HS256"//算法
}

2.载荷(playload)

  载荷就是存放用户信息、和有效数据的地方。它一共有三个部分组成

(1)标准中注册的声明

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

(2)公共的声明

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

(3)私有的声明

  私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息。这个指的自定义的信息,这些信息跟JWT标准规定的信息区别在于:JWT规定的信息,JWT的接收方在拿到JWT之后,都知道怎么对这些标准的信息进行验证(还不知道是否能够验证);而私有的信息不会验证,除非明确告诉接收方要对这些信息进行验证以及规则才行。如下例子:

{
    "iss":"xiaoming", //标准声明
    "name":"xiaowang", //私有声明
    "age":10//私有声明
}

3.签证

  jwt的第三部分是一个签证信息,这个签证信息由三部分组成:

  Header通过Base64加密的字符串 + playload通过Base64加密的字符串 + 秘钥

   完整的字符串如下:

eyJhbGciJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZ6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.VA95OrM7E2cBab3MHrcEfxjoYZgeFONFh7HgQ

  需要注意的是,秘钥是保存在服务端的,令牌签发也是在服务端,因此秘钥只能在服务器中,不能泄露出去,否则客户端能自己进行签发令牌。

   最重要的是签证的作用就是用来验证数据是否被进行了修改,根据签证生成规则可以看到,如果载荷中的信息被修改了,那么生成的字符串和签发的令牌一定是不相同的。

二、JWT的使用

1.引入maven

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.0</version>
</dependency>

2.令牌签发、解析实例

public static void main(String[] args) {
        String jwt=createJwt();
        System.out.println("签发的令牌:"+jwt);
        Claims claims=parseJwt(jwt);
        String jsonStr= JSON.toJSONString(claims);
        System.out.println(jsonStr);
    }

    /**
     * 签发令牌
     * @return
     */
    public static String createJwt(){
        JwtBuilder builder= Jwts.builder()
                .setId(UUID.randomUUID().toString().replace("-",""))             //设置唯一编号
                .setSubject("测试主题")       //设置发送的主题
                .setExpiration(new Date())  //设置过期时间
                .setIssuedAt(new Date())  //设置签发日期
                .signWith(SignatureAlgorithm.HS256,"abc");//设置签名 使用HS256算法,abc为私钥
       //设置用户信息
        Map<String,Object> map=new HashMap<>();
        map.put("name","小明");
        map.put("age",25);
        builder.addClaims(map);

        //构建 并返回一个字符串
        return builder.compact() ;
    }

    /**
     * 解析令牌
     * @param jwt
     * @return
     */
    public static Claims parseJwt(String jwt){
        Claims claims = Jwts.parser().
                setSigningKey("abc").//设置私钥
                parseClaimsJws(jwt).
                getBody();
       return claims;
    }

 

posted @ 2021-07-05 23:01  想去天空的猫  阅读(245)  评论(0编辑  收藏  举报