冷饭新炒:理解JWT的实现原理和基本使用 (3)

执行输出日志如下:

23:37:48.743 [main] INFO club.throwable.jwt.JsonWebToken - 生成的Header部分为:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 23:37:48.747 [main] INFO club.throwable.jwt.JsonWebToken - 生成的Payload部分为:eyJpc3MiOiJ0aHJvd3giLCJqaWQiOjEwMDg3LCJleHAiOjE2MTMyMjc0NjgxNjh9 23:37:48.748 [main] INFO club.throwable.jwt.JsonWebToken - 生成的Signature部分为:7skduDGxV-BP2p_CXyr3Na7WBvENNl--Pm4HQ8cJuEs 23:37:48.749 [main] INFO club.throwable.jwt.JsonWebToken - 生成的JWT为:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ0aHJvd3giLCJqaWQiOjEwMDg3LCJleHAiOjE2MTMyMjc0NjgxNjh9.7skduDGxV-BP2p_CXyr3Na7WBvENNl--Pm4HQ8cJuEs 自行生成的JWT:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ0aHJvd3giLCJqaWQiOjEwMDg3LCJleHAiOjE2MTMyMjc0NjgxNjh9.7skduDGxV-BP2p_CXyr3Na7WBvENNl--Pm4HQ8cJuEs

可以在jwt.io上验证一下:

冷饭新炒:理解JWT的实现原理和基本使用

解析JWT的过程是构造JWT的逆向过程,首先基于点号.分三段,然后分别进行BASE64解码,然后得到三部分的明文,头部参数和有效载荷需要做一次JSON反序列化即可还原各个部分的JSON结构:

public Map<Part, PartContent> parse(String jwt) throws Exception { System.out.println("当前解析的JWT:" + jwt); Map<Part, PartContent> result = new HashMap<>(8); // 这里暂且认为所有的输入JWT的格式都是合法的 StringTokenizer tokenizer = new StringTokenizer(jwt, DOT); String[] jwtParts = new String[3]; int idx = 0; while (tokenizer.hasMoreElements()) { jwtParts[idx] = tokenizer.nextToken(); idx++; } String headerPart = jwtParts[0]; PartContent headerContent = new PartContent(); headerContent.setRawContent(headerPart); headerContent.setPart(Part.HEADER); headerPart = new String(Base64.decodeBase64(headerPart), StandardCharsets.UTF_8); headerContent.setPairs(OBJECT_MAPPER.readValue(headerPart, new TypeReference<Map<String, Object>>() { })); result.put(Part.HEADER, headerContent); String payloadPart = jwtParts[1]; PartContent payloadContent = new PartContent(); payloadContent.setRawContent(payloadPart); payloadContent.setPart(Part.PAYLOAD); payloadPart = new String(Base64.decodeBase64(payloadPart), StandardCharsets.UTF_8); payloadContent.setPairs(OBJECT_MAPPER.readValue(payloadPart, new TypeReference<Map<String, Object>>() { })); result.put(Part.PAYLOAD, payloadContent); String signaturePart = jwtParts[2]; PartContent signatureContent = new PartContent(); signatureContent.setRawContent(signaturePart); signatureContent.setPart(Part.SIGNATURE); result.put(Part.SIGNATURE, signatureContent); return result; } enum Part { HEADER, PAYLOAD, SIGNATURE } @Data public static class PartContent { private Part part; private String rawContent; private Map<String, Object> pairs; }

这里尝试用之前生产的JWT进行解析:

public static void main(String[] args) throws Exception { JsonWebToken jsonWebToken = new JsonWebToken(); String jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ0aHJvd3giLCJqaWQiOjEwMDg3LCJleHAiOjE2MTMyMjc0NjgxNjh9.7skduDGxV-BP2p_CXyr3Na7WBvENNl--Pm4HQ8cJuEs"; Map<Part, PartContent> parseResult = jsonWebToken.parse(jwt); System.out.printf("解析结果如下:\nHEADER:%s\nPAYLOAD:%s\nSIGNATURE:%s%n", parseResult.get(Part.HEADER), parseResult.get(Part.PAYLOAD), parseResult.get(Part.SIGNATURE) ); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjzjp.html