Jwt令牌总结

1.Jwt令牌介绍
2.基于私钥生成jwt令牌
3.基于公钥解析jwt令牌
4.应用场景

1.Jwt令牌介绍

Jwt令牌主要由三部分组成头部,负载,签名,每个部分用点隔开

  • 头部主要包含令牌类型和使用的加密算法

  • 载荷主要存放信息,可以解码还原

  • 签名:

    签名=头部+载荷+签名
    头部和载荷都采用Base64Url编码和签名进行(用**.**进行)拼接生成签名

2.基于私钥生成Jwt令牌

准备私钥,公钥放入resource文件下,基于私钥携带数据生成jwt令牌

public class CreateJwtTest {
    /**
     * 创建令牌测试
     */
    @Test
    public void createJWT() {
        //基于私钥生成jwt
        //1. 创建一个秘钥工厂
        //1: 指定私钥的位置
        ClassPathResource classPathResource = new ClassPathResource("changgou.jks");
        //2: 指定秘钥库的密码
        String keyPass = "changgou";
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(classPathResource, keyPass.toCharArray());

        //2. 基于工厂获取私钥
        String alias = "changgou";
        String password = "changgou";
        KeyPair keyPair = keyStoreKeyFactory.getKeyPair(alias, password.toCharArray());
        //将当前的私钥转换为rsa私钥
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();

        //3.生成jwt

        //存储一些数据
        Map<String, String> map = new HashMap();
        map.put("company", "baidu");
        map.put("address", "beijing");

        Jwt jwt = JwtHelper.encode(JSON.toJSONString(map), new RsaSigner(rsaPrivateKey));
        String jwtEncoded = jwt.getEncoded();
        System.out.println(jwtEncoded);
    }
}

3.基于公钥解析jwt令牌

public class ParseJwtTest {

    /**
     * 校验令牌
     */
    @Test
    public void testParseToken() {
        //令牌
        String token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZGRyZXNzIjoiYmVpamluZyIsImNvbXBhbnkiOiJiYWlkdSJ9.JdtrwOQMvg6ZzP9zKvUZAXrd7zF_ufgi0ye_DQHeSukVwHXR9pN3MxQUCMp0uAawbFkCeNNglghbOflusDBK20qel5fZQLOZCAiL3kdx1z2Edvsu4QheTdRmNDtlA0vppmwWueRZgUrRiGK7GVhJeEOnNhp4DzKOSThy0XBdL6ECela7PHyGV1wyq51TxiDHK7onvTk2L-0CRoLwmqk27AsDd9X49Z-HnGxxSCpRBoEoVJEpVLo6qJxBYzpVN13zQqmefjb-tmgjeJaM-CtYHDvez-hkUj4Tu--sYtnBxbntiOCTFTztxOjs5AtLOK2B46qJbMZnxqYt15Nh6Rt-9A";

        //公钥
        String publicKey ="-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvFsEiaLvij9C1Mz+oyAmt47whAaRkRu/8kePM+X8760UGU0RMwGti6Z9y3LQ0RvK6I0brXmbGB/RsN38PVnhcP8ZfxGUH26kX0RK+tlrxcrG+HkPYOH4XPAL8Q1lu1n9x3tLcIPxq8ZZtuIyKYEmoLKyMsvTviG5flTpDprT25unWgE4md1kthRWXOnfWHATVY7Y/r4obiOL1mS5bEa/iNKotQNnvIAKtjBM4RlIDWMa6dmz+lHtLtqDD2LF1qwoiSIHI75LQZ/CNYaHCfZSxtOydpNKq8eb1/PGiLNolD4La2zf0/1dlcr5mkesV570NxRmU1tFm8Zd3MZlZmyv9QIDAQAB-----END PUBLIC KEY-----";

        //校验Jwt
        Jwt jwt = JwtHelper.decodeAndVerify(token,new RsaVerifier(publicKey));
		
		//获取jwt中存储的数据
        String claims = jwt.getClaims();
        System.out.println(claims);
        //jwt令牌
        String encoded = jwt.getEncoded();
        System.out.println(encoded);
    }
}

4.应用场景

1.用于微服务鉴权

1. 用户进入网关开始登陆,网关过滤器进行判断,如果是登录,则路由到后台管理微服务进 行登录 
2. 用户登录成功,后台管理微服务签发JWT TOKEN信息返回给用户 
3. 用户再次进入网关开始访问,网关过滤器接收用户携带的TOKEN 
4. 网关过滤器解析TOKEN ,判断是否有权限,如果有,则放行,如果没有则返回未认证错误

提供两个生产解析的jwt令牌的工具类
生成工具类

public class JwtUtil {

    //有效期为
    public static final Long JWT_TTL = 3600000L;// 60 * 60 *1000  一个小时
    //设置秘钥明文
    public static final String JWT_KEY = "baidu";

    /**
     * 创建token
     * @param id
     * @param subject
     * @param ttlMillis
     * @return
     */
    public static String createJWT(String id, String subject, Long ttlMillis) {

        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        if(ttlMillis==null){
            ttlMillis=JwtUtil.JWT_TTL;
        }
        long expMillis = nowMillis + ttlMillis;
        Date expDate = new Date(expMillis);
        SecretKey secretKey = generalKey();

        JwtBuilder builder = Jwts.builder()
                .setId(id)              //唯一的ID
                .setSubject(subject)   // 主题  可以是JSON数据
                .setIssuer("admin")     // 签发者
                .setIssuedAt(now)      // 签发时间
                .signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥
                .setExpiration(expDate);// 设置过期时间
        return builder.compact();
    }

    /**
     * 生成加密后的秘钥 secretKey
     * @return
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }

    /**
     * 解析
     *
     * @param jwt
     * @return
     * @throws Exception
     */
    public static Claims parseJWT(String jwt) throws Exception {
        SecretKey secretKey = generalKey();
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(jwt)
                .getBody();
    }
}

颁发令牌,使用场景

 if (login) {
                //登录成功,生成令牌,返回jwt令牌 和用户名
                HashMap<String, String> map = new HashMap<>();
                map.put("LoginName",admin.getLoginName());
                String token = JwtUtil.createJWT(UUID.randomUUID().toString(), admin.getLoginName(), null);
                map.put("token",token);
                return new Result(true, StatusCode.OK, "登录成功",map);
            }
        }

解析令牌,使用场景,在网关服务中定义拦截器,进行鉴权操作

public class AuthorizeFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1.获取请求对象
        ServerHttpRequest request = exchange.getRequest();
        //2.获得响应对象
        ServerHttpResponse response = exchange.getResponse();
        //3.判断是否为登录请求,是就放行
        String path = request.getURI().getPath();
        if (path.contains("/admin/login")){
            return chain.filter(exchange);
        }
        //4. 获取请求头信息
        HttpHeaders headers = request.getHeaders();
        //5.获取jwt令牌信息
        String jwtToken = headers.getFirst("token");
        //6.判断当前令牌是否存在,不存在,返回错误信息
        if (jwtToken == null) {
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        //6.1存在,判断是否合法,不合法返回错误信息
        //6.2存在,合法,放行
        try {
            JwtUtil.parseJWT(jwtToken);
        }catch (Exception e){
            e.printStackTrace();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        return  chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值