当前位置:   article > 正文

Spring Cloud Gateway(读取、修改 Request Body)_modifyrequestbodygatewayfilterfactory

modifyrequestbodygatewayfilterfactory

Spring Cloud Gateway(以下简称 SCG)做为网关服务,是其他各服务对外中转站,通过 SCG 进行请求转发。

在请求到达真正的微服务之前,我们可以在这里做一些预处理,比如:来源合法性检测,权限校验,反爬虫之类…

之前是在各个微服务的拦截器里对来解密验证的,现在既然有了网关,自然而然想把这一步骤放到网关层来统一解决
 

Spring Cloud(十八):Spring Cloud Gateway(读取、修改 Request Body)

如果是使用普通的 Web 编程中(比如用 Zuul),这本就是一个 pre filter 的事儿,把之前 Interceptor 中代码搬过来稍微改改就 OK 了。

不过因为使用的 SCG,它基于 Spring 5 的 WebFlux,即 Reactor 编程,要读取 Request Body 中的请求参数就没那么容易了。

创建自定义过滤器继承AbstractGatewayFilterFactory

  1. @Component
  2. @Slf4j
  3. public class ReqApiPermissionFilterFactory extends AbstractGatewayFilterFactory<ReqApiPermissionFilterFactory.Config> {
  4. public ReqApiPermissionFilterFactory() {
  5. super(ReqApiPermissionFilterFactory.Config.class);
  6. }
  7. static class Config {
  8. }
  9. @Value("${token.user.url}")
  10. String userURL;
  11. @Value("${middle.platform.url}")
  12. String middlePlatformURL;
  13. private static final String CONTENT_TYPE = "Content-Type";
  14. private static final String CONTENT_TYPE_JSON = "application/json";
  15. @Override
  16. public GatewayFilter apply(ReqApiPermissionFilterFactory.Config config) {
  17. return (exchange, chain) -> {
  18. ServerHttpRequest request = exchange.getRequest();
  19. String contentType = request.getHeaders().getFirst(CONTENT_TYPE);
  20. String method = request.getMethodValue();
  21. if (null != contentType && HttpMethod.POST.name().equalsIgnoreCase(method) && contentType.contains(CONTENT_TYPE_JSON)) {
  22. ModifyRequestBodyGatewayFilterFactory.Config modifyRequestConfig = new ModifyRequestBodyGatewayFilterFactory.Config()
  23. .setContentType(ContentType.APPLICATION_JSON.getMimeType())
  24. .setRewriteFunction(Map.class, Map.class, (exchange1, originalRequestBody) -> {
  25. boolean isPass = validateApiPermission(exchange1, originalRequestBody);
  26. if(!isPass){
  27. throw new ResultException(GatewayErrorCode.PERMISSION_ERROR,
  28. ImmutableMap.of("originalRequestBody", originalRequestBody));
  29. }
  30. return Mono.just(originalRequestBody);
  31. });
  32. return new ModifyRequestBodyGatewayFilterFactory().apply(modifyRequestConfig).filter(exchange, chain);
  33. }
  34. if (HttpMethod.GET.name().equalsIgnoreCase(method)) {
  35. Map<String,Object> query = request.getQueryParams().entrySet()
  36. .stream()
  37. .collect(Collectors.toMap(
  38. Map.Entry::getKey,
  39. Map.Entry::getValue
  40. ));
  41. boolean isPass = validateApiPermission(exchange, query);
  42. if(!isPass){
  43. throw new ResultException(GatewayErrorCode.PERMISSION_ERROR,
  44. ImmutableMap.of("query", query));
  45. }
  46. return chain.filter(exchange.mutate().request(request).build());
  47. }
  48. return chain.filter(exchange);
  49. };
  50. }
  51. @Override
  52. public String name() {
  53. return "ReqApiPermission";
  54. }
  55. /**
  56. * 判断用户权限
  57. *
  58. * @param exchange
  59. * @param requestParameters
  60. * @return
  61. */
  62. private boolean validateApiPermission(ServerWebExchange exchange, Map<String,Object> requestParameters) {
  63. log.debug("接口请求参数:{}", requestParameters);
  64. /***实现
  65. }
  66. }

至于拿到 Body 后具体要做什么,就由你自己来发挥吧

我这里是做了整个平台服务的鉴权功能。

在配置文件里添加修改

  1. predicates:
  2. - Path=/openapi/**
  3. filters:
  4. - AuthorizationSignature
  5. - ReqApiPermission
  6. - RewritePath=/openapi/(?<remaining>.*), /${remaining}

这样同样的路径可以会被两个过滤器同时过滤。

其他的实现方式可参考如下链接:Spring Cloud Gateway 之获取请求体(Request Body)的几种方式 - 码农的进击 - 博客园

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号