JWT介绍和使用

embedded/2024/10/18 14:16:25/

JWT_0">JWT介绍和使用

JWT_1">JWT介绍

JWT(JSON Web Token)是一个开放的标准(RFC 7519),JWT定义了一种简介的、自包含的协议格式。可以用于在通信的双方传递json对象,传递的信息可以被信任,因为信息是被数字签名的。JWT可以使用HMAC算法或者使用RSA/ECDSA算法的公钥/私钥对签名。

JWT_4">JWT格式

JWT包含三部分内容,Header、Plyload和Signature。

  • Header

    • 包括令牌的类型以及使用的哈希算法;使用base64url编码后就是JWT的第一部分内容
  • Payload

    • Payload的内容是一个json对象,它是存放有效信息的地方,可以存放jwt提供的现成字段,比如:iss(签发者),exp(过期时间戳信) ,sub(面向的用户)等;同时也可以自定义字段存放数据,但是不建议存放敏感数据,因为此部分可以解码还原原始内容;使用base64url编码后就是JWT的第二部分内容
  • Signature

    • Signature是签名,用于防止jwt内容被篡改,这个部分使用base64url将前两部分进行编码,编码后使用“.” 连接组成字符串,最后使用header中声明的签名算法进行签名。

假设现在一个JWT的Header和Payload部分内容如下
Header:

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

payload

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

那么Signature的的内容如下所示,“yguyhdqwodqwddqw1”是秘钥

HMACSHA384(base64UrlEncode(header) + "." +base64UrlEncode(payload),yguyhdqwodqwddqw1
)

最后生成的JWT如下:

eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.f7IalcwE38sVPor1FBUwAwso6exiwF80y0nM6bLkAvooNFGjCoJXRL0DMpaQB42C

payload和claims介绍

payload和claims的概念在JJWT开源库中使用了,所以这里简单介绍一下。

前面已经讲过了payload是一个JSON对象,包含了实际传输的数据。而Payload的主要目的是携带与特定用户或请求相关的信息,这些信息就被称为“claims”。

Claims(声明)是Payload中包含的具体键值对数据项,它们用来表述特定的声明或声明集,这些声明描述了与JWT相关的事实。根据其用途和规范要求,claims可以分为以下几类:

  • Reserved Claims(保留声明): 这些是JWT标准中预定义的、具有特殊含义的claims。虽然它们是可选的,但如果使用,应遵循标准规定的名称和格式。常见的保留claims包括:
    • iss(issuer):签发者。
    • sub(subject):主题,标识JWT所代表的个体。
    • aud(audience):接收方,标识预期的JWT接收者。
    • exp(expiration time):过期时间,定义了JWT的有效期截止时间。
    • nbf(not before):生效时间,在此时间之前JWT不应被接受处理。
    • iat(issued at):签发时间,表明JWT的创建时间。
    • jti(JWT ID):唯一标识符,用于防止JWT重放攻击。
  • Public Claims(公共声明)
    • 这些claims没有在JWT标准中明确规定,但可以通过IANA JSON Web Token Registry进行注册,以确保其名称在全球范围内是唯一的,避免不同系统间的冲突。公共claims通常用于满足特定的应用程序或行业需求。
  • Private Claims(私有声明)
    • 开发者可以自由定义的claims,用于承载应用程序所需的任何额外信息。私有claims无需注册,其名称由开发者自行决定,如示例中提到的user_id和user_name。这些声明对JWT的使用者具有特定意义,但对JWT标准本身来说是无特殊含义的。

JWT_69">JWT使用

jjwt是Java Json Web Tokens的缩写,它所示一个用于在Java中实现JWT的开源库。

jjwt依赖

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.11.2</version></dependency><!-- javax.xml.bind.DatatypeConverter 类已被弃用并从 Java SE 9 中移除--><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.1</version></dependency>

这是自己写的JJWT工具类

java">public class JJWTUtils {private static final Logger logger = LoggerFactory.getLogger(JJWTUtils.class);private static final String SECRET = "mpd';dqw823djq3d902";/*** 生成token*/public static String getToken(Map<String, Object> map) {//设置内容JwtBuilder jwtBuilder = Jwts.builder().setClaims(map);Calendar instance = Calendar.getInstance();instance.add(Calendar.SECOND, 100);//设置过期时间, 100s后过期jwtBuilder.setExpiration(instance.getTime());String token = jwtBuilder.signWith(SignatureAlgorithm.HS256, SECRET.getBytes()).compact();return token;}/*** 校验token* @param token  jwt字符串* @return*/public static boolean verifyToken(String token) {String[] tokenSplit = token.split(".");String header = tokenSplit[0];String payload = tokenSplit[1];String signature = tokenSplit[2];String headerJson = new String(Base64.getDecoder().decode(header));String payloadJson = new String(Base64.getDecoder().decode(payload));byte[] keyBytes = SECRET.getBytes(StandardCharsets.UTF_8);Key signingKey = Keys.hmacShaKeyFor(keyBytes);// 验证JWT签名,如果JWT签名无效,这里会抛出SignatureException异常boolean result = true;try {Jwts.parser().setSigningKey(signingKey).parse(token);} catch (Exception e) {result = false;}return result;}/*** 获取token中的携带的信息*/public static Map<String, Object> getPayload(String token) {//claims是一个Map,存放了通过JwtBuilder设置进去的内容Claims claims = Jwts.parser().setSigningKey(SECRET.getBytes()).parseClaimsJws(token).getBody();return claims;}public static void main(String[] args) {HashMap<String, Object> payload = new HashMap<>();payload.put("name", "张三");payload.put("id", "1");String token = JJWTUtils.getToken(payload);logger.info("token: " + token);Map<String, Object> payload1 = JJWTUtils.getPayload(token);logger.info("payload1: " + payload1);}}

jjwt使用的坑

问题1
java.lang.ClassNotFoundException: javax.xml.bind.DatatypeConverter at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) … 6 more

解决方法
这个错是由于在Java8以后,javax.xml.bind.DatatypeConverter 类已被弃用并从 Java SE 9 中移除而导致的,所以加入缺少的依赖即可

        <dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.1</version></dependency>

问题2
ava.lang.IllegalStateException: Both ‘payload’ and ‘claims’ cannot both be specified. Choose either one. at io.jsonwebtoken.impl.DefaultJwtBuilder.compact(DefaultJwtBuilder.java:262) at com.example.sso.utils.JJWTUtils.getToken(JJWTUtils.java:38) at com.example.sso.utils.JJWTUtils.main(JJWTUtils.java:58)

解决方法

不能同时设置payload和claims。

参考

  1. Introduction to JSON Web Tokens

http://www.ppmy.cn/embedded/21232.html

相关文章

python:根据旋转平移矩阵求取原始点云或者转换后点云

根据旋转平移矩阵求取原始点云或者转换后点云 原始点云进行旋转平移示例 1示例 2示例 3示例 4 根据转换后点云及转换矩阵求原始点云示例 1示例 2示例 3示例 4 原始点云进行旋转平移 转换前的点云可以表示为一个N行3列的矩阵&#xff0c;每一行代表一个点的坐标。我们定义一个旋…

项目记录:一个C语言模拟操作系统的程序(1)

记录一个我的C语言做的非常简单的小项目&#xff0c;本大冤种帮一个上大一的远房堂弟&#xff08;不知道叫堂还是表了&#xff0c;反正是我妈亲戚家的&#xff09;做的课程设计&#xff0c;要求做的是一个字符图形界面的操作系统模拟。等他答辩完&#xff0c;无偿贡献给大家~给…

web服务的部署及高级优化方案

[rootserver100 桌面]# vmset.sh 100 [rootserver100 桌面]# dnf install nginx.x86_64 -y [rootserver100 nginx]# vim nginx.conf root /var/www/html; [rootserver100 nginx]# mkdir -p /var/www/html [rootserver100 nginx]# echo /var/www/html > /var/www/html/index…

【数据结构6--图】

目录 1 图2 图的定义和基本概念&#xff08;在简单图范围内&#xff09;3 图的类型定义4 图的存储结构4.1 邻接矩阵 表示法4.2 邻接表 表示法4.3 十字链表 表示法4.4 邻接多重表 表示法 5 图的遍历5.1 深度优先搜索-DFS 及 广度优先遍历-BFS 6 图的应用6.1 最小生成树6.1.1 克鲁…

windows下的文件路径怎么在pycharm中使用(python)

在Windows操作系统中&#xff0c;文件路径的格式与Unix/Linux系统略有不同&#xff0c;主要在于路径分隔符的使用。Windows系统通常使用反斜杠&#xff08;\&#xff09;作为路径分隔符&#xff0c;而Unix/Linux系统使用正斜杠&#xff08;/&#xff09;。当在Python中处理文件…

APP自定义身份证相机(Android +iOS)

基本上同时兼容安卓和苹果的插件都需要付费&#xff0c;这里我找了2个好用的免费插件 1.仅支持安卓&#xff1a;自定义身份证相机&#xff08;支持蒙版自定义&#xff09;&#xff0c;内置蒙版&#xff0c;照片预览&#xff0c;身份证裁剪 - DCloud 插件市场、 2.支持iOS(已测…

【黑马点评Redis——004达人探店】

1.发布探店笔记 2.点赞 利用Redis中的Set集合来判断是否点赞过。 3.点赞排行榜 可以通过SortedSet来按点赞时间进行排序。 4.好友关注 4.1.关注和取关 4.2.共同关注 可以通过set实现交集的功能 4.3.关注推送 4.3.1 拉模式 拉模式&#xff08;Pull&#xff09;&#x…

git tag管理

1. Git 创建tag并推送到云端 首先&#xff0c;在本地创建一个新的tag&#xff0c;可以使用 -a 选项添加带有注释信息的annotated tag&#xff0c;或直接创建lightweight tag。例如&#xff0c;若要标记最近一次提交为 v1.0 并附带注释信息&#xff1a; # 创建带有注释信息的a…