详细解析 JWT 的实现原理及其在 Web 应用中的应用。
chou403
/ Safety
/ c:
/ u:
/ 5 min read
jwt是怎么实现的
JSON Web Token (JWT) 是一种基于 JSON 的开放标准(RFC 7519)用于在网络应用环境间传递声明。JWT 是一种紧凑的,URL 安全的方式,用于表示一组信息。它由三部分组成: 头部(Header),载荷(Payload)和签名(Signature)。以下是 JWT 的实现细节及其工作原理:
JWT 组成部分
-
Header: 头部通常包括两部分: 令牌类型(即 JWT)和所使用的签名算法(如 HMAC SHA256 或 RSA)。
{ "alg": "HS256", "typ": "JWT" }
-
Payload: 载荷部分包含声明(claims)。声明是有关实体(通常是用户)及其他数据的声明。声明可以分为三类:
- Registered claims: 预定义的声明集,但不是强制的,例如
iss
(发行者),exp
(过期时间),sub
(主题),aud
(受众)。 - Public claims: 可以随意定义的声明,但为了避免冲突,应该在 IANA JSON Web Token Registry 或使用包含倒数域名的自定义名称空间中定义。
- Private claims: 自定义声明,通常是双方协商使用的声明。
{ "sub": "1234567890", "name": "John Doe", "admin": true }
- Registered claims: 预定义的声明集,但不是强制的,例如
-
Signature: 签名部分是通过将编码后的头部,编码后的载荷,以及一个密钥组合在一起,然后使用指定的签名算法生成的。
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
JWT 工作原理
-
创建 JWT: 服务器在用户登录时验证用户身份,通过使用头部和载荷创建 JWT,然后用签名算法和密钥对其进行签名。生成的 JWT 令牌会返回给客户端。
-
存储 JWT: 客户端将收到的 JWT 令牌存储在浏览器的 Local Storage 或 Cookie 中。
-
发送 JWT: 客户端在每次请求时,将 JWT 令牌放在 HTTP 请求的 Authorization 头部中发送给服务器。
Authorization: Bearer <token>
-
验证 JWT: 服务器接收到请求后,会验证 JWT 的签名和声明(例如过期时间)。如果验证通过,则处理请求;否则,返回401未授权状态。
实现 JWT 示例(Java)
以下是使用 Java 和 jjwt 库实现 JWT 的一个简单示例:
依赖项(Maven)
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
创建 JWT
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
public class JwtExample {
private static final String SECRET_KEY = "mySecretKey";
public static String createJwt(String id, String issuer, String subject, long ttlMillis) {
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
// JWT 构建器
return Jwts.builder()
.setId(id)
.setIssuedAt(now)
.setSubject(subject)
.setIssuer(issuer)
.setExpiration(new Date(nowMillis + ttlMillis))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public static void main(String[] args) {
String jwt = createJwt("123", "issuer", "subject", 3600000);
System.out.println("Generated JWT: " + jwt);
}
}
验证 JWT
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
public class JwtExample {
private static final String SECRET_KEY = "mySecretKey";
public static Claims decodeJwt(String jwt) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(jwt)
.getBody();
}
public static void main(String[] args) {
String jwt = createJwt("123", "issuer", "subject", 3600000);
System.out.println("Generated JWT: " + jwt);
Claims claims = decodeJwt(jwt);
System.out.println("ID: " + claims.getId());
System.out.println("Subject: " + claims.getSubject());
System.out.println("Issuer: " + claims.getIssuer());
System.out.println("Expiration: " + claims.getExpiration());
}
}
安全注意事项
- 密钥管理: 密钥必须安全存储,不能硬编码在代码中,应使用环境变量或安全的配置管理工具。
- 过期时间: 设置合理的过期时间,避免长期有效的令牌被滥用。
- HTTPS: 在传输 JWT 时,确保使用 HTTPS 以防止中间人攻击。
通过以上步骤,您可以在 Java 应用中实现 JWT 生成和验证机制。不同语言有不同的库和实现方式,但核心原理是一致的。