张家港做网站广告公司,做网站要素,服务器网站建设软件有哪些,软件开发平台方案JWT
什么是 JWT
JSON Web Token#xff0c;通过数字签名的方式#xff0c;以 JSON 对象为载体#xff0c;在不同的服务终端之间安全地传输信息
官网#xff1a;https://jwt.io/SDK: https://jwt.io/libraries (含Java和各种语言)Java SDK(上面的SDK链接得到): https://g…JWT
什么是 JWT
JSON Web Token通过数字签名的方式以 JSON 对象为载体在不同的服务终端之间安全地传输信息
官网https://jwt.io/SDK: https://jwt.io/libraries (含Java和各种语言)Java SDK(上面的SDK链接得到): https://github.com/auth0/java-jwt (java sdk也有很多种这是其中一种)可以根据自己的喜好选择 SDK不同的SDK的API设计有差异那自然会有好坏本项目种使用的 SDK 也是官方推荐的其中一种选官方的比来路不明的好
JWT 有什么用
JWT 最常见的场景就是授权认证一旦用户登录后续每个请求都将包含JWT系统在每次处理用户请求之前都要先进行 JWT 安全校验通过之后再进行处理。
JWT 的组成
JWT 由 3 部分组成用 . 拼接
格式是 Header.Payload.Signature
Header头信息
{typ: JWT,alg: HS256
}包含类型typ和算法alg类型写死 JWT算法可以自己决定这里用HS256举例
Payload
实际的有效数据你要传的业务数据例如
Signature
Signature是这么算出来的var encodedString base64UrlEncode(header) . base64UrlEncode(payload);
var signature HMACSHA256(encodedString, your_secret);说明
1、header和payload先用base64加密用点链接起来再用header里alg所指定的算法计算摘要
2、your_secret 就是秘钥加密方和解密方共同知道的解密的时候要用补充
当你拿到一段jwt字符串的时候就是三段式的那串你能知道什么
对于 xxx.yyy.zzz你可以知道
xxx可以用base64解密xxxyyy本以为base64不能解密结果可以另外我也遇到过不能解密的可能是自己额外加密了zzz不能base64解密
注意不要整段粘贴进去用base64解密要分段否则可能会出现解密不了的情况。
例子
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0ZWFjaGVyIjp7Im5hbWUiOiJNaXNzIExlZSJ9LCJzZXgiOnRydWUsIm5hbWUiOiJTdG9uZSIsImNvdXJzZUxpc3QiOlt7Im5hbWUiOiJNYXRoIiwiY3JlZGl0cyI6NH0seyJuYW1lIjoiRW5nbGlzaCIsImNyZWRpdHMiOjN9XSwiZXhwIjoxNjkxNDExMzcyLCJhZ2UiOjIwfQ.C2LJfyeeS2E0tpS12o-MnQWvn3B7ecK_ul3kudpiAPE注意一定要分段粘贴进去进行base64解密不要一整个整体本例子没有问题有些别的例子会出现yyy部分不能解密的情况base64解密第一段{typ:JWT,alg:HS256}
base64解密第一段{teacher:{name:Miss Lee},sex:true,name:Stone,courseList:[{name:Math,credits:4},{name:English,credits:3}],exp:1691411372,age:20}
base64解密第一段乱码看来是解密不了Java 例子
其实实际的使用过程Java 作为后端仅仅需要写解析jwt的对于封装这是前端要干的事情。
package com.wyf.test.jwt;import io.jsonwebtoken.*;import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;public class JWTTest {private static final String MY_SECRET xAy23hz23YK;// 加解密用的秘钥public static void main(String[] args) throws InterruptedException {String jwtString testGetJwtString();//Thread.sleep(4*1000);// 模拟超市的情况是否能检查出来System.out.println(\n-------------------\n);testParseJwtString(jwtString);}// 得到加密的字符串这个一般来说不是Java写的肯定是前端人员写的JS(react/vue等public static String testGetJwtString() {/*格式Header.Payload.Signatureheader的格式是{typ: JWT,alg: HS256}其中类型typ写死alg可选这里选HS256算法Payload 是实际的数据Signature的计算方式如下(参考如下用JS写的伪代码var encodedString base64UrlEncode(header) . base64UrlEncode(payload);var signature HMACSHA256(encodedString, your_secret);其中 your_secret 就是秘钥加密方和解密方共同知道的解密的时候要用*/// 设置 token 有效期long tokenLifespan 3 * 1000; // 30 秒Date expireDateTime new Date(System.currentTimeMillis() tokenLifespan);// 用 Java 中引入的 JWT 包里的 APIJwtBuilder jwtBuilder Jwts.builder();String jwtString jwtBuilder// header.setHeaderParam(typ, JWT).setHeaderParam(alg, HS256)// payload claim 其实就是payload的意思就是你要传的数据.setClaims(prepareMapPayloadData())// 可选设置 token 有效期.setExpiration(expireDateTime)// signature (解密的时候用的secret不对的话会抛出signature无法匹配的异常io.jsonwebtoken.SignatureException: JWT signature does not match locally computed signature..signWith(SignatureAlgorithm.HS256, MY_SECRET)// 用点连接起来.compact();System.out.println(jwtString: jwtString);System.out.println(token duration(Sec): (tokenLifespan / 1000));SimpleDateFormat simpleDateFormat new SimpleDateFormat(yyyy-MM-dd HH:mm:ss.SSSZ);simpleDateFormat.setTimeZone(TimeZone.getTimeZone(GMT8));System.out.println(expireDateTime: simpleDateFormat.format(expireDateTime));return jwtString;}// 我在想这个方法根本就不需要返回payload里的值如果使用JWT仅仅是validate一下signature是不是正确的、达到鉴权效果就可以了public static Object testParseJwtString(String jwtString) {JwtParser jwtParser Jwts.parser();// 设置解密用的秘钥解密的时候用的secret不对的话会抛出signature无法匹配的异常jwtParser.setSigningKey(MY_SECRET);// parse 的时候就会校验签名不正确的时候会从这行抛出异常也会校验token是否超时如果超时爆出// Exception in thread main io.jsonwebtoken.ExpiredJwtException: JWT expired at 2023-08-07T18:59:42Z. Current time: 2023-08-07T18:59:44Z, a difference of 2416 milliseconds. Allowed clock skew: 0 milliseconds.Jwt parse jwtParser.parse(jwtString);Header header parse.getHeader();Object body parse.getBody();// 其API是设计成用Object接收的System.out.println(header: (header ! null ? header.getClass().toString() , header : null));System.out.println(body: (body ! null ? body.getClass().toString() , body : null));return body;}/*** method to convert object to a map* param obj* return* throws IllegalAccessException*/public static MapString, Object getObjectToMap(Object obj) throws IllegalAccessException {MapString, Object map new HashMapString, Object();Class? cla obj.getClass();Field[] fields cla.getDeclaredFields();for (Field field : fields) {field.setAccessible(true);String keyName field.getName();Object value field.get(obj);if (value null)value ;map.put(keyName, value);}return map;}public static MapString, Object prepareMapPayloadData() {MapString, Object objectToMap;try {objectToMap getObjectToMap(preparePayloadData());} catch (IllegalAccessException e) {throw new RuntimeException(e);}System.out.println(payload map: objectToMap);return objectToMap;}public static Student preparePayloadData() {ListCourse courseList new ArrayListCourse();Course course1 new Course();course1.setName(Math);course1.setCredits(4);Course course2 new Course();course2.setName(English);course2.setCredits(3);courseList.add(course1);courseList.add(course2);Teacher teacher new Teacher();teacher.setName(Miss Lee);Student student new Student();student.setName(Stone);student.setAge(20);student.setSex(true);student.setTeacher(teacher);student.setCourseList(courseList);return student;}public static class Student {private String name;private Integer age;private Boolean sex;private Teacher teacher;private ListCourse courseList;public String getName() {return name;}public void setName(String name) {this.name name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age age;}public Boolean getSex() {return sex;}public void setSex(Boolean sex) {this.sex sex;}public Teacher getTeacher() {return teacher;}public void setTeacher(Teacher teacher) {this.teacher teacher;}public ListCourse getCourseList() {return courseList;}public void setCourseList(ListCourse courseList) {this.courseList courseList;}}public static class Teacher {private String name;public String getName() {return name;}public void setName(String name) {this.name name;}}public static class Course {private String name;private Integer credits;public String getName() {return name;}public void setName(String name) {this.name name;}public Integer getCredits() {return credits;}public void setCredits(Integer credits) {this.credits credits;}}
}