认证过程在Gateway网关层面实现。在网关中添加过滤器,获取携带的Token信息,验证该Token是否合法;Token合法则放行,否则拦截。如果系统需要获取Token中的信息(例如userId等),可以将其放在Http中。

全局过滤器实现jwt校验

com.swx.app.gateway模块下创建包com.swx.app.gateway.filter

创建过滤器类

AuthorizeFilter
@Component
public class AuthorizeFilter implements Ordered, GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1. 获取Request和Response对象
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();

// 2. 判断是否是登陆
if (request.getURI().getPath().contains("/login")) {
return chain.filter(exchange);
}

// 3. 获取Token
String token = request.getHeaders().getFirst("token");

// 4. 判断Token是否存在
if (!StringUtils.hasText(token)) {
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}

// 5. 判断Token是否有效
Claims claimsBody = AppJwtUtil.getClaimsBody(token);
int result = AppJwtUtil.verifyToken(claimsBody);
if (result == 1 || result == 2) {
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
// 6. 放行
return chain.filter(exchange);
}

/**
* 优先级设置,值越小,优先级越高
* @return
*/
@Override
public int getOrder() {
return 0;
}
}

工具类

utils.AppJwtUtil
public class AppJwtUtil {
// TOKEN的有效期一天(S)
private static final int TOKEN_TIME_OUT = 3_600;
// 加密KEY
private static final String TOKEN_ENCRY_KEY = "Nvz9Vywt6NuTM7l07RoWvN86M84frPcZuj83SHwpM3S6k2GdPq4QQOjS1IZHIjWt";
// 最小刷新间隔(S)
private static final int REFRESH_TIME = 300;

// 生产ID
public static String getToken(Long id) {
Map<String, Object> claimMaps = new HashMap<>();
claimMaps.put("id", id);
long currentTime = System.currentTimeMillis();
return Jwts.builder()
.setId(UUID.randomUUID().toString())
.setIssuedAt(new Date(currentTime)) //签发时间
.setSubject("system") //说明
.setIssuer("heima") //签发者信息
.setAudience("app") //接收用户
.compressWith(CompressionCodecs.GZIP) //数据压缩方式
.signWith(generalKey(), SignatureAlgorithm.HS512) //加密方式
.setExpiration(new Date(currentTime + TOKEN_TIME_OUT * 1000)) //过期时间戳
.addClaims(claimMaps) //cla信息
.compact();
}

/**
* 获取token中的claims信息
*
* @param token
* @return
*/
private static Jws<Claims> getJws(String token) {
return Jwts.parser()
.setSigningKey(generalKey())
.parseClaimsJws(token);
}

/**
* 获取payload body信息
*
* @param token
* @return
*/
public static Claims getClaimsBody(String token) {
try {
return getJws(token).getBody();
} catch (ExpiredJwtException e) {
return null;
}
}

/**
* 获取hearder body信息
*
* @param token
* @return
*/
public static JwsHeader getHeaderBody(String token) {
return getJws(token).getHeader();
}

/**
* 是否过期
*
* @param claims
* @return -1:有效,0:有效,1:过期,2:过期
*/
public static int verifyToken(Claims claims) {
if (claims == null) {
return 1;
}
try {
claims.getExpiration()
.before(new Date());
// 需要自动刷新TOKEN
if ((claims.getExpiration().getTime() - System.currentTimeMillis()) > REFRESH_TIME * 1000) {
return -1;
} else {
return 0;
}
} catch (ExpiredJwtException ex) {
return 1;
} catch (Exception e) {
return 2;
}
}

/**
* 由字符串生成加密key
*
* @return
*/
public static SecretKey generalKey() {
byte[] encodedKey = Base64.getEncoder().encode(TOKEN_ENCRY_KEY.getBytes());
return Keys.hmacShaKeyFor(encodedKey);
}
}