了解 JWT 和 Java-JWT 在 Web 应用中的应用和实现
1. 什么是JWT?
JWT全称为Json Web Token,是一种用于身份验证和授权的开放标准。它将一些声明(例如用户身份信息)作为JSON对象进行传输,使用数字签名或加密确保数据的安全性。
2. JWT的基本结构
一个JWT主要由头部(Header)、载荷(Payload)和签名(Signature)三部分构成,它们使用Base64字符串进行编码。
- 头部(Header):包含描述 JWT 的元数据,例如指定使用的算法(如HMAC SHA256或RSA)。
- 载荷(Payload):存储有关用户的信息,以及其他自定义的声明。
- 签名(Signature):使用私钥(或密钥)对头部和载荷进行加密生成的签名,用于验证数据的完整性和真实性。
2.1 头部(Header)
头部通常由两部分组成:令牌类型(typ)和签名算法(alg)。令牌类型通常是"JWT",而签名算法可以是HMAC、RSA或者其他加密算法。
示例:
{
"typ": "JWT",
"alg": "HS256"
}
2.2 载荷(Payload)
载荷是JWT的主要信息存储部分,通常包含一些声明(claims)和一些自定义的数据。声明分为三种类型:注册声明、公共声明和私有声明。
注册声明包括iss(签发者)、sub(面向的用户)、aud(接收方)、exp(过期时间)、iat(签发时间)和nbf(生效时间)等。
公共声明包括可以自定义的一些属性,但建议避免冲突。
私有声明包括自定义的一些属性,用于满足应用程序的需求。
示例:
{
"sub": "1234567890",
"name": "小王",
"admin": true
}
2.3 签名(Signature)
签名部分使用Base64编码的头部和载荷,加上一个密钥(secret)通过指定的算法计算出来。通过对头部、载荷和密钥进行加密,可以验证数据在传输过程中是否被篡改。
示例:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
2.4 JWT 的工作原理
JWT 的工作原理如下:
- 客户端使用私钥和头部和载荷生成签名,并将头部、载荷和签名组合成一个字符串形式的 JWT。
- 客户端将 JWT 发送给服务器。
- 服务器使用存储的公钥对接收到的 JWT 进行验证和解析。
- 如果验证成功,服务器可以信任 JWT 中的信息,并根据需要执行相应的操作。
那么它在web应用里的工作流程如下:
2.5 JWT 的优势和应用场景
JWT 具有以下优势和适用场景:
- 简洁:JWT 使用 JSON 格式表示信息,具有可读性和简洁性。
- 安全:通过签名验证和密钥加密,确保 JWT 的完整性和机密性。
- 可扩展:JWT 的载荷支持自定义声明,可根据需求存储丰富的信息。
- 无状态:服务器不需要在每次请求中保存会话信息,提高系统的可伸缩性。
JWT 在身份验证、单点登录、API 授权等场景中得到广泛应用。
3. Java-JWT简介
Java-JWT是一个用于生成和解析JWT的Java库,提供了简单易用的API和一些常用的功能。
3.1 添加依赖
你可以通过 Maven 或直接下载 jar 包的方式引入 Java-JWT。
Maven:
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.18.2</version>
</dependency>
Gradle:
implementation 'com.auth0:java-jwt:3.18.2'
3.2 生成JWT
下面是一个使用Java-JWT生成JWT的示例代码:
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import java.util.Date;
// 生成JWT
String secret = "your-secret";
Algorithm algorithm = Algorithm.HMAC256(secret);
String token = JWT.create()
.withIssuer("your-issuer")
.withSubject("your-subject")
.withAudience("your-audience")
.withExpiresAt(new Date(System.currentTimeMillis() + 3600000))
.withIssuedAt(new Date())
.sign(algorithm);
System.out.println(token);
输出结果:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ5b3VyLWlzc3VlciIsInN1YiI6InlvdXItc3ViamVjdCIsImF1ZCI6InlvdXItYXVkaWVuY2UiLCJleHAiOjE2MzU1MzEzNzUsImlhdCI6MTYzNTUyNTc3NX0.7DkLDaiwD8q9dNzA7zY9EDcH2hQ8iZTnFyF4YIgohoA
3.3 解析JWT
下面是一个使用Java-JWT解析JWT的示例代码:
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
// 解析JWT
String token = "your-token";
String secret = "your-secret";
Algorithm algorithm = Algorithm.HMAC256(secret);
try {
JWTVerifier verifier = JWT.require(algorithm)
.withIssuer("your-issuer")
.withSubject("your-subject")
.withAudience("your-audience")
.build();
DecodedJWT jwt = verifier.verify(token);
System.out.println("Token verified");
System.out.println("Subject: " + jwt.getSubject());
System.out.println("Issued At: " + jwt.getIssuedAt());
System.out.println("Expires At: " + jwt.getExpiresAt());
} catch (JWTVerificationException e) {
System.out.println("Token verification failed");
e.printStackTrace();
}
输出结果:
Token verified
Subject: your-subject
Issued At: Mon Sep 04 11:41:29 CST 2023
Expires At: Mon Sep 04 11:41:29 CST 2023
4. 总结
本文介绍了JWT的基本概念和结构,并展示了使用Java-JWT生成和解析JWT的示例代码。通过使用JWT,我们可以实现简单且安全的身份验证和授权机制。