全局过滤器 (GlobalFilter)

SpringCloud Gateway 支持自定义过滤器,可以很灵活的进行请求或者响应的控制。

自定义过滤器的方法是实现 GlobalFilter 接口、实现 Ordered 接口。这两个接口的全路径为:

  • org.springframework.cloud.gateway.filter.GlobalFilter
  • org.springframework.core.Ordered

获取请求参数

通关拦截请求参数我们可以作鉴权、限流等

通过实现 GlobalFilter 和 Ordered 这两个接口中的 filter(进行全局过滤)和 getOrder(指定过滤器的优先级)方法

其中,FilterChain 维护了一个链表,链表中存放着配置对象的链条,每次用户调用 一次 chain.doFilter(request, response),链表就去取下一个配置对象,再通过配置对象 得到下一个 filter,然后调用该 filter,接着在 filter 里写的逻辑就被执行了。

@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE)
@Component
public class AuthorizeFilter implements GlobalFilter {
 
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
      	// 获取请求头
        HttpHeaders headers = exchange.getRequest().getHeaders();
        // 获取请求参数
        MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
        // 获取用户名称
        String username = params.getFirst("username");
        // 请求路径
        String requestPath = String.valueOf(exchange.getRequest().getPath());
        log.info("网关路由路径:{}",requestPath);
        // 校验
        if ("admin".equals(username)) {
         // 放行
         return chain.filter(exchange);  
        }
       	//禁止访问,设置状态码
         exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
         // 结束处理
         return exchange.getResponse().setComplete();
    }
}
 
 

获取响应报文

通关拦截响应报文我们可以修改响应报文 例如身份证号,手机号码脱敏

@Component
@Slf4j
public class ResponseGlobalFilter implements GlobalFilter, Ordered {
 
    @Resource
    private RedisTemplate<String,Integer> redisTemplate;
 
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取响应
        ServerHttpResponse originalResponse = exchange.getResponse();
        DataBufferFactory bufferFactory = originalResponse.bufferFactory();
        // 获取请求参数
        MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
        // 获取用户名称
        String username = params.getFirst("username");
        ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                if (body instanceof Flux) {
                    Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
                    return super.writeWith(fluxBody.buffer().map(dataBuffers -> {//解决返回体分段传输
                        StringBuffer stringBuffer = new StringBuffer();
                        dataBuffers.forEach(dataBuffer -> {
                            byte[] content = new byte[dataBuffer.readableByteCount()];
                            dataBuffer.read(content);
                            DataBufferUtils.release(dataBuffer);
                            try {
                                stringBuffer.append(new String(content, "utf-8"));
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        });
                        String result = stringBuffer.toString();
                        log.info("响应报文:{}",result);
                    	//这里可以修改返回内容,返回内容是JSON字符串
                        byte[] uppedContent = new String(result.getBytes(), Charset.forName("UTF-8")).getBytes();
                        originalResponse.getHeaders().setContentLength(uppedContent.length);
                        return bufferFactory.wrap(uppedContent);
                    }));
                }
                return super.writeWith(body);
            }
        };
        return chain.filter(exchange.mutate().response(decoratedResponse).build());
    }
 
    @Override
    public int getOrder() {
        return -2;
    }
}