@Slf4j
@Component
public class LogTimeGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
private static long timeSpan = 0;
@Override
public GatewayFilter apply(NameValueConfig config) {
String timeSpanStr = config.getValue();
timeSpan = Long.valueOf(timeSpanStr);
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
long startTime = System.currentTimeMillis();
return chain.filter(exchange).then(Mono.fromRunnable(()->{
long endTime = System.currentTimeMillis();
long time = endTime-startTime;
if(time >= timeSpan){
log.debug("{} 耗时:{}",exchange.getRequest().getURI(), time);
}
}));
}
};
}
}
目的是对所有进入系统的请求或相应进行统一处理
@Slf4j
@Component
public class TokenFilter implements GlobalFilter, Ordered {
@Value("${cn.smart.tokenx.key}")
private String tokenKey;
private static List<String> whiteList = CollUtil.newArrayList("/api/login", "/api/register");
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
URI uri = request.getURI();
String path = uri.getPath().toLowerCase().trim();
//排除白名单的验证
if(whiteList.contains(path)){
return chain.filter(exchange);
}
ServerHttpResponse response = exchange.getResponse();
List<String> tokens = request.getHeaders().get("token");
//验证的是有没有传token
if(ObjectUtil.isEmpty(tokens)){
log.error("请传token");
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
String token = tokens.get(0);
//验证的是传的token值是否为空
if(ObjectUtil.isEmpty(token)){
log.error("token 不能为空");
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
boolean b = false;
// 验证算法,JWTValidator包含过期的验证,验证比较全面
try {
JWTValidator.of(token).validateAlgorithm(JWTSignerUtil.hs256(tokenKey.getBytes())).validateDate();
b = true;
}catch (Exception ex){
ex.printStackTrace();
log.error("token不正确");
}
if(!b){
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
//接着执行下面的过滤器,token还会带到下游,我们的服务还是要用我们之前的token-starter,token-starter功能只保留解析token写入Threadlocal,验证的功能不再需要
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 2;
}
}
@Component
@Slf4j
@Order(1)
public class TraceIdFilter implements GlobalFilter {
private static final String TRACE_ID = "traceId";
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
List<String> traceIds = request.getHeaders().get(TRACE_ID);
if(ObjUtil.isNotEmpty(traceIds)){
return chain.filter(exchange);
}
String traceId = IdUtil.simpleUUID();
//request.getHeaders().set(TRACE_ID,traceId); //ReadOnlyHttpHeaders UnsupportedOperationException
ServerHttpRequest request2 = request.mutate().header(TRACE_ID,traceId).build();
return chain.filter(exchange.mutate().request(request2).build());
}