Java 有许多比较知名的生成 JWT(JSON WEB TOKEN)的开源工具库。例如
选择性比较多,本文以常用的 auth0 组织下的 java-jwt 为例。
在 pom.xml
文件中引入 java-jwt
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.19.1</version>
</dependency>
编写一个 JwtUtil 工具类,用以生成 Token 令牌以及校验 Token 令牌。该工具类还需要依赖一个配置类来实现。
@Component
public class JwtUtil {
private static String tokenSecret;
private static Long tokenExpire;
private static Algorithm algorithm;
@Autowired
public JwtUtil(JwtConfig jwtConfig, UserService userService) {
JwtUtil.tokenSecret = jwtConfig.getTokenSecret();
JwtUtil.tokenExpire = jwtConfig.getTokenExpire();
JwtUtil.algorithm = Algorithm.HMAC512(JwtUtil.tokenSecret);
JwtUtil.userService = userService;
}
/**
* 生成Token
*/
public static String generateToken(String userId) {
long now = new Date().getTime();
Date expireDate = new Date(now + (JwtUtil.tokenExpire));
return JWT.create()
.withClaim("userId", userId)
.withExpiresAt(expireDate)
.sign(JwtUtil.algorithm);
}
/**
* 验证Token
*/
public static boolean verifyToken(String token) {
try {
JWTVerifier verifier = JWT.require(JwtUtil.algorithm)
.acceptExpiresAt(JwtUtil.tokenExpire)
.build();
verifier.verify(token);
return true;
} catch (TokenExpiredException e) {
throw new TokenExpired();
} catch (JWTVerificationException e) {
throw new TokenInvalid();
}
}
/**
* 获取Claim
*/
public static String getClaim(String token, String claimKey) {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaims().get(claimKey).asString();
}
}
@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "jwt")
public class JwtConfig {
private String tokenSecret;
private Long tokenExpire;
}
JwtUtil 可以在授权登录成功后生成令牌,并下发至客户端。
String token = JwtUtil.generateToken(user.getId());
使用拦截器,拦截校验 JWT 令牌是否合法。
@Component
public class JwtInterceptor implements HandlerInterceptor {
public final static String AUTHORIZATION_HEADER = "Authorization";
public final static String BEARER_PATTERN = "^Token$";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = verifyAuthorizationHeader(request);
return JwtUtil.verifyToken(token);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
LocalUser.clearLocalUser();
}
/**
* 验证请求头是否携带Token
*/
private String verifyAuthorizationHeader(HttpServletRequest request) {
String authorization = request.getHeader(AUTHORIZATION_HEADER);
if (authorization == null) {
throw new AuthorizationException();
}
String[] splits = authorization.split(" ");
if (splits.length != 2) {
throw new AuthorizationException();
}
String scheme = splits[0];
String token = splits[1];
if (!Pattern.matches(BEARER_PATTERN, scheme)) {
throw new AuthorizationException();
}
return token;
}
}