概述
头部(Header): 包含了描述JWT的元数据及签名算法的信息,通常由两部分组成:令牌类型(typ)和使用的加密算法(alg),例如
{"typ": "JWT", "alg": "HS256"}
。载荷(Payload): 包含了用户的声明(claims),比如用户的ID、角色等信息,以及其他需要传递的数据。载荷分为三类:
- 注册声明(Registered claims):预定义的一些声明,如
iss
(Issuer)、exp
(Expiration time)、sub
(Subject)等。 - 公共声明(Public claims):自定义的声明,用于在使用JWT的双方定义自己的声明内容。
- 私有声明(Private claims):用于在同意使用的各方之间共享信息,而不是注册在 IANA 中或以其他方式被注册的声明。
- 注册声明(Registered claims):预定义的一些声明,如
签名(Signature): 使用私钥对头部和载荷进行签名,确保数据在传输过程中没有被篡改。签名的目的是验证消息的完整性以及发送者的身份。
作用
JWT 的主要作用是在用户和服务器之间安全地传输信息,特别适用于无状态(stateless)和分布式应用环境。它提供了一种简单且高效的方法来进行身份验证和授权,同时减少了服务器端存储和查询会话状态的需求。
应用场景
- 身份认证(Authentication): 用户登录后,服务器生成JWT并返回给客户端,客户端在后续请求中携带JWT来验证身份。
- 信息交换(Information Exchange): 可以在不同的系统之间安全地传输信息。
- 单点登录(Single Sign-On): 用户登录一个应用后,可以无需再次登录访问其他关联的应用。
- 权限验证(Authorization): 可以使用JWT来传递用户的角色和权限信息,确保用户在访问受保护资源时具有相应的权限。
示例代码
下面是一个简单的 Java 示例,演示如何使用 Java JWT 库(例如 jjwt
)创建和验证JWT。
首先,确保你的项目中包含了 jjwt
依赖,例如 Maven 中的配置:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
接下来,示例代码如下:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
public class JwtExample {
// 生成JWT
public static String generateJwt(String userId, String username, long expirationMillis, String secretKey) {
Date now = new Date();
Date expiration = new Date(now.getTime() + expirationMillis);
return Jwts.builder()
.setSubject(username)
.claim("userId", userId)
.setIssuedAt(now)
.setExpiration(expiration)
.signWith(SignatureAlgorithm.HS256, secretKey)
.compact();
}
// 解析JWT
public static Claims parseJwt(String jwt, String secretKey) {
return Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(jwt)
.getBody();
}
public static void main(String[] args) {
// 假设以下为用户登录成功后生成JWT的示例
String userId = "123";
String username = "john.doe";
String secretKey = "mysecretkey";
long expirationMillis = 3600000; // 1 hour
String jwt = generateJwt(userId, username, expirationMillis, secretKey);
System.out.println("Generated JWT: " + jwt);
// 假设以下为服务器接收到JWT并验证的示例
try {
Jws<Claims> claims = parseJwt(jwt, secretKey);
System.out.println("Username: " + claims.getBody().getSubject());
System.out.println("User ID: " + claims.getBody().get("userId", String.class));
System.out.println("Expiration: " + claims.getBody().getExpiration());
} catch (Exception e) {
System.out.println("JWT parsing or validation error: " + e.getMessage());
}
}
}
在示例中:
generateJwt
方法用于生成JWT,设置了用户ID、用户名,设置了过期时间,并使用 HMAC SHA-256 签名算法进行签名。parseJwt
方法用于解析和验证JWT,通过传入的秘钥来验证JWT的有效性,并提取其中的信息。
这个示例展示了如何使用 JWT 在用户登录和服务器验证之间传递信息,确保信息的完整性和安全性。