JwtToken的使用和介绍
什么是 JSON Web Token?
JSON Web 令牌 (JWT) 是一种开放标准 (RFC 7519),它定义了一种紧凑且独立的方式,用于在各方之间以 JSON 对象的形式安全地传输信息。此信息可以验证和信任,因为它是经过数字签名的。JWT 可以使用密钥(使用 HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对进行签名。
尽管 JWT 可以加密以提供各方之间的保密性,但我们将专注于签名令牌。签名令牌可以验证其中包含的声明的完整性,而加密令牌则向其他方隐藏这些声明。当使用公钥/私钥对对令牌进行签名时,签名还证明只有持有私钥的一方才是签名的一方。
何时应使用 JSON Web 令牌?
以下是 JSON Web 令牌有用的一些方案:
- 授权:这是使用 JWT 的最常见方案。用户登录后,每个后续请求都将包含 JWT,允许用户访问使用该令牌允许的路由、服务和资源。单点登录是当今广泛使用 JWT 的一项功能,因为它的开销很小,并且能够跨不同域轻松使用。
- 信息交换:JSON Web 令牌是在各方之间安全传输信息的好方法。由于 JWT 可以签名(例如,使用公钥/私钥对),因此您可以确定发件人是他们所说的人。此外,由于签名是使用标头和有效负载计算的,因此您还可以验证内容是否未被篡改。
什么是 JSON Web 令牌结构?
JSON Web 令牌的紧凑形式由由点 () 分隔的三个部分组成,分别是:.
- 页眉
- 有效载荷
- 签名
因此,JWT 通常如下所示。
xxxxx.yyyyy.zzzzz
让我们分解不同的部分。
头部(Header)
标头通常由两部分组成:令牌的类型(即 JWT)和正在使用的签名算法,例如 HMAC SHA256 或 RSA。
例如:
{
"alg": "HS256",
"typ": "JWT"
}
然后,此JSON被Base64Url编码以形成JWT的第一部分。
有效载荷(Payload)
令牌的第二部分是有效负载,其中包含声明。声明是有关实体(通常是用户)和其他数据的语句。 有三种类型的声明:已注册、公共和私人声明。
-
已注册声明:这些是一组预定义的声明,这些声明不是必需的,但建议使用,以提供一组有用的、可互操作的声明。其中一些是:
iss 【issuer】发布者的url地址
sub 【subject】该JWT所面向的用户,用于处理特定应用,不是常用的字段
aud 【audience】接受者的url地址
exp 【expiration】 该jwt销毁的时间;unix时间戳
nbf 【not before】 该jwt的使用时间不能早于该时间;unix时间戳
iat 【issued at】 该jwt的发布时间;unix 时间戳
jti 【JWT ID】 该jwt的唯一ID编号
请注意,声明名称只有三个字符长,因为 JWT 应该是紧凑的。
-
公共声明:这些可以由使用 JWT 的人随意定义。但为了避免冲突,它们应该在IANA JSON Web 令牌注册表中定义,或者定义为包含抗冲突命名空间的 URI。
-
专用声明:这些是创建的自定义声明,用于在同意使用它们的各方之间共享信息,既不是注册声明也不是公共声明。
示例有效负载可以是:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
然后对有效负载进行 Base64Url 编码以形成 JSON Web 令牌的第二部分。
请注意,对于签名令牌,此信息虽然受到篡改保护,但任何人都可以读取。不要将机密信息放在 JWT 的有效负载或标头元素中,除非它已加密。
签名(Signature)
要创建签名部分,您必须获取编码的标头、编码的有效负载、机密、标头中指定的算法并对其进行签名。
例如,如果要使用 HMAC SHA256 算法,将按以下方式创建签名:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
签名用于验证消息在此过程中未被更改,并且在使用私钥签名的令牌的情况下,它还可以验证 JWT 的发件人是否是它所说的人。
把所有东西放在一起
头部、载荷、签名用.号连接在一起就得到了我们想要的JWT。输出是三个由点分隔的 Base64-URL 字符串,可以在 HTML 和 HTTP 环境中轻松传递,同时与基于 XML 的标准(如 SAML)相比更加紧凑。
下面显示了对以前的标头和有效负载进行了编码并使用机密进行签名的 JWT。
如果要使用 JWT 并将这些概念付诸实践,可以使用调试器 jwt.io 解码、验证和生成 JWT。
JAVA 实现
JAVA中使用JWT
使用Maven引入和Gradle引入
Maven
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
Gradle
dependencies { compile 'io.jsonwebtoken:jjwt:0.9.0' }
JWT依赖于Jackson,需要在程序中加入Jackson的jar包且版本大于2.x
签发创建JWT
public static String createToken() {
// 创建一个JwtBuilder对象
JwtBuilder jwtBuilder = Jwts.builder();
String token = jwtBuilder
// Header
.setHeaderParam("typ", "JWT")
.setHeaderParam("alg", "HS256")
// PayLoad
.claim("username", "Jack") // 自定义属性
.claim("role", "admin") // 自定义属性
.setId(UUID.randomUUID().toString()) // JWT_ID
.setSubject("admin-test") // 主题
.setAudience("") // 接收者
.setIssuer("") // 签发者
.setIssuedAt(new Date()) // 签发时间
.setNotBefore(new Date()) // 失效时间
.setExpiration(new Date(System.currentTimeMillis() + time)) // 过期时间
// Signature
.signWith(SignatureAlgorithm.HS256, "secretKey") // 签名算法以及密钥
.compact();
return token;
}
解析JWT
public void parserJwt(String token) {
// 创建一个JwtParser对象
JwtParser jwtParser = Jwts.parser();
// 类似Map集合
Jws<Claims> claimsJws = jwtParser.setSigningKey("admin") // 盐值
.parseClaimsJws(token);// 将JWT转化成一个Key-Value,通过Key来获取对应的Value
// 获取Jwt对象中的数据:get(key)表示根据key来获取value
Claims claims = claimsJws.getBody();// 存储的是用户保存的数据
System.out.println(claims.get("username"));
System.out.println(claims.get("role"));
System.out.println(claims.getSubject());
System.out.println(claims.getExpiration());
System.out.println(claims.getId());
}
验证JWT
public void checkJwt(String token) {
// 创建一个JwtParser对象
JwtParser jwtParser = Jwts.parser();
boolean result = jwtParser.isSigned(token); // 判断Token是否正确
System.out.println(result);
}
输出示例
创建Token
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InRvbSIsInJvbGUiOiJhZG1pbiIsInN1YiI6ImFkbWluLXRlc3QiLCJleHAiOjE2OTQwNTM4OTksImp0aSI6IjE5NWYzOTRjLTJmMjMtNDk2ZC1iYjI4LTdhOTFkMTQ4YzUwMSJ9.5EVp5F6GE2rEd8KOr5sWrdlEJ7cybW9nhvQv5viMbf8
解析Token
tom
admin
admin-test
Thu Sep 07 10:31:39 CST 2023
195f394c-2f23-496d-bb28-7a91d148c501
标签:令牌,JWT,JSON,签名,JwtToken,使用,声明
From: https://www.cnblogs.com/lxh-daniel/p/17684028.html