在Spring Cloud Gateway中GlobalFilter可以方便的全局拦截或统计,有时候希望在某些路由中可以跳过GlobalFilter,可以通过GatewayFilter与GlobalFilter组合来实现。
1、全局过滤器GlobalFilter
详细代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| package com.chanjet.dsf.web.filter;
import com.alibaba.fastjson.JSON; import com.chanjet.dsf.cache.RedisUtil; import com.chanjet.dsf.constant.AttrbuteConstant; import com.chanjet.dsf.constant.ResultCodeEnum; import com.chanjet.dsf.result.ResultFactory; import com.chanjet.dsf.web.models.AuthTokenPo; import com.chanjet.dsf.web.util.Constant; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
@Component public class AuthFilter implements GlobalFilter, Ordered {
Logger logger = LoggerFactory.getLogger(AuthFilter.class);
private static final String TOKEN_PREFIX = "DSFTOKEN::";
@Autowired RedisUtil redisUtil;
@Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String token = exchange.getRequest().getQueryParams().getFirst(Constant.QUERY_PARAMS.TOKEN);
logger.info("=======AuthFilter:token======" + token); if (exchange.getAttribute(AttrbuteConstant.ATTRIBUTE_IGNORE_TEST_GLOBAL_FILTER) != null && exchange.getAttribute(AttrbuteConstant.ATTRIBUTE_IGNORE_TEST_GLOBAL_FILTER).equals(true)) { return chain.filter(exchange); }
if (StringUtils.isEmpty(token)) { return generateJSON(exchange, ResultFactory.getErrorResult(ResultCodeEnum.TOKEN_IS_NULL)); } String rediskey = TOKEN_PREFIX + token; try { AuthTokenPo authTokenPo = (AuthTokenPo) redisUtil.get(rediskey); if (authTokenPo == null) { return generateJSON(exchange, ResultFactory.getErrorResult(ResultCodeEnum.TOKEN_IS_INVALID)); }
} catch (Exception e) { logger.error("AuthFilter.filter 错误信息{}", e.getMessage(), e); } return chain.filter(exchange); } private <T>Mono generateJSON(ServerWebExchange exchange, T t){ ServerHttpResponse response = exchange.getResponse(); byte[] bits = JSON.toJSONString(t).getBytes(StandardCharsets.UTF_8); DataBuffer buffer = response.bufferFactory().wrap(bits); response.setStatusCode(HttpStatus.UNAUTHORIZED); response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8"); return response.writeWith(Mono.just(buffer)); }
@Override public int getOrder() { return -900; } }
|
2、AbstractGatewayFilterFactory 局部过滤器
内部类写法,是为了指定过滤器的优先级,要优先于全局过滤器,否则
容易造成全局过滤器拦截到指定局部过滤器的配置内容,从而导致局
部过滤器失效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| package com.chanjet.dsf.web.filter;
import com.chanjet.dsf.constant.AttrbuteConstant; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.core.Ordered; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono;
@Component public class IgnoreAuthFilter extends AbstractGatewayFilterFactory<IgnoreAuthFilter.Config> {
Logger logger = LoggerFactory.getLogger(IgnoreAuthFilter.class);
public IgnoreAuthFilter() { super(Config.class); logger.info("IgnoreFilter 进入 IgnoreAuthGatewayFilterFactory "); }
@Override public GatewayFilter apply(Config config) { logger.info("IgnoreFilter 进入 apply"); return new InnerFilter(config); }
private class InnerFilter implements GatewayFilter, Ordered {
private Config config;
InnerFilter(Config config) { this.config = config; }
@Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { logger.info("进入innerFilter=====" + config.isIgnoreGlobalFilter()); if (config.isIgnoreGlobalFilter() == true) { exchange.getAttributes().put(AttrbuteConstant.ATTRIBUTE_IGNORE_TEST_GLOBAL_FILTER, true); } return chain.filter(exchange); }
@Override public int getOrder() { return -1000; } }
public static class Config{ boolean ignoreGlobalFilter;
public boolean isIgnoreGlobalFilter() { return ignoreGlobalFilter; }
public void setIgnoreGlobalFilter(boolean ignoreGlobalFilter) { this.ignoreGlobalFilter = ignoreGlobalFilter; } }
@Override public String name() { return "IgnoreAuthFilter"; } }
|
3、yml配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| spring: cloud: gateway: discovery: locator: enabled: true lower-case-service-id: true routes: - id: dsf-report-ser uri: lb://dsf-report-ser predicates: - Path=/report/** - id: dsf-account-ser uri: lb://dsf-account-ser predicates: - Path=/account/**,/setting/** filters: - name: IgnoreAuthFilter args: ignoreGlobalFilter: true - id: dsf-finance-ser uri: lb://dsf-finance-ser predicates: - Path=/shopTrade/**,/goods/**,/cost/**
|