JSON Web Tokens (JWT) 是一种用于身份验证和授权的开放标准。JWT 是一个自包含的令牌,它在客户端和服务端之间传输时包含了所有必要的信息,这使得 JWT 成为了无状态应用的理想选择,尤其是在分布式环境中。
JWT 原理
JWT 包含三部分:Header(头部)、Payload(载荷)和 Signature(签名)。
- Header:
-
- 包含关于 JWT 的元数据,比如所使用的签名算法(如 HMAC SHA256 或 RSA)和 JWT 类型(通常是 JWT)。
- 示例:
{"alg":"HS256","typ":"JWT"}
- 这部分经过 Base64URL 编码。
- Payload:
-
- 包含实际需要传输的信息,比如用户ID、用户名等。
- 示例:
{"sub":"1234567890","name":"John Doe","admin":true}
- 这部分也经过 Base64URL 编码。
- Signature:
-
- 由 JWT 发行人使用一个秘密(secret)或私钥,结合 Header 和 Payload 生成。
- 保证了 JWT 的完整性和防篡改性。
JWT 三部分通过点(.
)连接起来,形成完整的 JWT 字符串。
Spring Boot 整合 JWT
在 Spring Boot 中使用 JWT 主要涉及以下几个步骤:
1. 引入依赖
<!-- JWT -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.14.0</version>
</dependency>
2. 生成 JWT
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
public class JwtUtil {
private static final String SECRET = "your_secret_key";
public static String generateToken(String userId) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MINUTE, 30);
return JWT.create()
.withSubject("User Details")
.withClaim("userId", userId)
.withExpiresAt(calendar.getTime())
.sign(Algorithm.HMAC256(SECRET));
}
}
3. 解析 JWT
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
public class JwtUtil {
public static DecodedJWT decodeToken(String token) {
return JWT.require(Algorithm.HMAC256(SECRET))
.build()
.verify(token);
}
}
4. 创建拦截器
为了保护某些端点,你需要创建一个拦截器来检查每个请求中的 JWT。
import com.auth0.jwt.exceptions.TokenExpiredException;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = request.getHeader("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
// Unauthorized
return false;
}
token = token.substring(7);
try {
// Verify and decode the token
JwtUtil.decodeToken(token);
return true;
} catch (TokenExpiredException e) {
// Token expired
} catch (Exception e) {
// Other exceptions
}
// Unauthorized
return false;
}
}
5. 注册拦截器
在 Spring Boot 配置类中注册你的拦截器。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JwtInterceptor())
.addPathPatterns("/api/protected/**")
.excludePathPatterns("/api/public/**");
}
}
使用示例
在用户登录时生成 JWT,并在后续的受保护 API 请求中,通过 HTTP Authorization header 发送 JWT。拦截器将验证 JWT 是否有效并决定是否允许请求继续。