From 96e47407f077bf386f3258ae9bac876b01a9dc1e Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 9 Aug 2019 12:46:46 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A8=E6=80=81=E4=BF=AE=E6=94=B9=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../files/10111_动态修改请求参数.md | 33 ++++++++ .../sop/gatewaycommon/bean/ApiConfig.java | 4 +- .../manager/ParameterFormatter.java | 7 +- .../configuration/BaseZuulConfiguration.java | 11 ++- .../zuul/filter/BaseZuulFilter.java | 7 +- .../filter/PreParameterFormatterFilter.java | 42 +++++++++++ .../zuul/filter/PreValidateFilter.java | 8 -- .../zuul/param/ZuulParameterFormatter.java | 10 +++ ...rFormatter.java => ZuulParameterUtil.java} | 75 ++++++++++++++----- 9 files changed, 160 insertions(+), 37 deletions(-) create mode 100644 doc/docs/files/10111_动态修改请求参数.md create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreParameterFormatterFilter.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParameterFormatter.java rename sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/{BaseParameterFormatter.java => ZuulParameterUtil.java} (63%) diff --git a/doc/docs/files/10111_动态修改请求参数.md b/doc/docs/files/10111_动态修改请求参数.md new file mode 100644 index 00000000..90f2f7f4 --- /dev/null +++ b/doc/docs/files/10111_动态修改请求参数.md @@ -0,0 +1,33 @@ +# 动态修改请求参数 + +自1.14.0开始,zuul网关支持动态修改请求参数。即在网关修改客户端传递过来的参数,然后发送到微服务端。 + +``` +客户端参数{"name": "jim"} --> zuul中修改为{"name": "Lucy"} --> 微服务端将收到{"name": "Lucy"} +``` + +使用场景:客户端请求参数经过加密,在网关解密后,再次发送明文参数给微服务端 + +- 如何使用 + +在网关springboot启动函数中添加如下代码 + +```java +public static void main(String[] args) { + ApiConfig.getInstance().setZuulParameterFormatter(requestParams -> { + // 获取biz_content + JSONObject jsonObject = requestParams.getJSONObject(ParamNames.BIZ_CONTENT_NAME); + // 修改biz_content中的值 + jsonObject.put("name", "name修改了111"); + jsonObject.put("remark", "remark修改了222"); + // 重新设置biz_content + requestParams.put(ParamNames.BIZ_CONTENT_NAME, jsonObject); + }); + SpringApplication.run(SopGatewayApplication.class, args); +} + +``` + +其中requestParams是客户端传递过来的参数,直接修改其中的值即可。 + +更多参考:com.gitee.sop.gatewaycommon.zuul.filter.PreParameterFormatterFilter.java diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java index e0bbabbd..ab6fb813 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java @@ -15,7 +15,6 @@ import com.gitee.sop.gatewaycommon.manager.EnvGrayManager; import com.gitee.sop.gatewaycommon.manager.IPBlacklistManager; import com.gitee.sop.gatewaycommon.manager.IsvRoutePermissionManager; import com.gitee.sop.gatewaycommon.manager.LimitConfigManager; -import com.gitee.sop.gatewaycommon.manager.ParameterFormatter; import com.gitee.sop.gatewaycommon.manager.RouteConfigManager; import com.gitee.sop.gatewaycommon.manager.ServiceErrorManager; import com.gitee.sop.gatewaycommon.param.ParamBuilder; @@ -35,6 +34,7 @@ import com.gitee.sop.gatewaycommon.validate.Signer; import com.gitee.sop.gatewaycommon.validate.Validator; import com.gitee.sop.gatewaycommon.zuul.configuration.ZuulErrorController; import com.gitee.sop.gatewaycommon.zuul.param.ZuulParamBuilder; +import com.gitee.sop.gatewaycommon.zuul.param.ZuulParameterFormatter; import com.gitee.sop.gatewaycommon.zuul.result.ZuulResultExecutor; import com.netflix.zuul.context.RequestContext; import lombok.Data; @@ -150,7 +150,7 @@ public class ApiConfig { */ private ZuulErrorController zuulErrorController = new ZuulErrorController(); - private ParameterFormatter zuulParametersFormatter; + private ZuulParameterFormatter zuulParameterFormatter; // -------- fields --------- diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ParameterFormatter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ParameterFormatter.java index 4e51cf11..8fd2caf7 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ParameterFormatter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ParameterFormatter.java @@ -1,19 +1,18 @@ package com.gitee.sop.gatewaycommon.manager; -import com.alibaba.fastjson.JSONObject; +import java.util.Map; /** * 参数格式化 * * @author tanghc */ -public interface ParameterFormatter { +public interface ParameterFormatter> { /** * 参数格式化,即动态修改请求参数 * * @param requestParams 原始请求参数,在此基础上追加或修改参数 - * @param requestContext requestContext */ - void format(JSONObject requestParams, T requestContext); + void format(T requestParams); } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java index 62063af4..e93c5a33 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java @@ -1,5 +1,6 @@ package com.gitee.sop.gatewaycommon.zuul.configuration; +import com.alibaba.fastjson.JSONObject; import com.gitee.sop.gatewaycommon.bean.ApiConfig; import com.gitee.sop.gatewaycommon.bean.ApiContext; import com.gitee.sop.gatewaycommon.manager.AbstractConfiguration; @@ -11,6 +12,7 @@ import com.gitee.sop.gatewaycommon.zuul.filter.FormBodyWrapperFilterExt; import com.gitee.sop.gatewaycommon.zuul.filter.PostResultFilter; import com.gitee.sop.gatewaycommon.zuul.filter.PreHttpServletRequestWrapperFilter; import com.gitee.sop.gatewaycommon.zuul.filter.PreLimitFilter; +import com.gitee.sop.gatewaycommon.zuul.filter.PreParameterFormatterFilter; import com.gitee.sop.gatewaycommon.zuul.filter.PreValidateFilter; import com.gitee.sop.gatewaycommon.zuul.filter.PreVersionDecisionFilter; import com.gitee.sop.gatewaycommon.zuul.filter.Servlet30WrapperFilterExt; @@ -47,8 +49,8 @@ public class BaseZuulConfiguration extends AbstractConfiguration { @Bean @ConditionalOnMissingBean - ParameterFormatter preParamFilter(){ - return ApiConfig.getInstance().getZuulParametersFormatter(); + ParameterFormatter preParamFilter(){ + return ApiConfig.getInstance().getZuulParameterFormatter(); } /** @@ -111,6 +113,11 @@ public class BaseZuulConfiguration extends AbstractConfiguration { return new PreValidateFilter(); } + @Bean + PreParameterFormatterFilter preParameterFormatterFilter() { + return new PreParameterFormatterFilter(); + } + /** * 开启限流 */ diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/BaseZuulFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/BaseZuulFilter.java index 29b97e4f..2147c1f3 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/BaseZuulFilter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/BaseZuulFilter.java @@ -23,11 +23,14 @@ public abstract class BaseZuulFilter extends ZuulFilter { /** 签名验证过滤 */ public static final int PRE_VALIDATE_FILTER_ORDER = -1000; + /** 参数格式化过滤器 */ + public static final int PRE_PARAMETER_FORMATTER_FILTER_ORDER = PRE_VALIDATE_FILTER_ORDER + 1; + /** 权限验证过滤 */ - public static final int PRE_ROUTE_PERMISSION_FILTER_ORDER = PRE_VALIDATE_FILTER_ORDER + 1; + public static final int PRE_ROUTE_PERMISSION_FILTER_ORDER = PRE_VALIDATE_FILTER_ORDER + 100; /** 限流过滤 */ - public static final int PRE_LIMIT_FILTER_ORDER = PRE_ROUTE_PERMISSION_FILTER_ORDER + 1; + public static final int PRE_LIMIT_FILTER_ORDER = PRE_ROUTE_PERMISSION_FILTER_ORDER + 100; private Integer filterOrder; diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreParameterFormatterFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreParameterFormatterFilter.java new file mode 100644 index 00000000..9f88470c --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreParameterFormatterFilter.java @@ -0,0 +1,42 @@ +package com.gitee.sop.gatewaycommon.zuul.filter; + +import com.gitee.sop.gatewaycommon.param.ApiParam; +import com.gitee.sop.gatewaycommon.param.ParamNames; +import com.gitee.sop.gatewaycommon.zuul.ZuulContext; +import com.gitee.sop.gatewaycommon.zuul.param.ZuulParameterFormatter; +import com.gitee.sop.gatewaycommon.zuul.param.ZuulParameterUtil; +import com.netflix.zuul.context.RequestContext; +import com.netflix.zuul.exception.ZuulException; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * 参数格式化过滤器,动态修改参数,此过滤器放在前面校验后面 + * + * @author tanghc + */ +public class PreParameterFormatterFilter extends BaseZuulFilter { + + @Autowired(required = false) + private ZuulParameterFormatter zuulParameterFormatter; + + @Override + protected FilterType getFilterType() { + return FilterType.PRE; + } + + @Override + protected int getFilterOrder() { + return PRE_PARAMETER_FORMATTER_FILTER_ORDER; + } + + @Override + protected Object doRun(RequestContext requestContext) throws ZuulException { + ApiParam apiParam = ZuulContext.getApiParam(); + // 校验成功后进行参数转换 + if (zuulParameterFormatter != null) { + ZuulParameterUtil.format(apiParam, zuulParameterFormatter::format); + requestContext.addZuulRequestHeader(ParamNames.HEADER_VERSION_NAME, apiParam.fetchVersion()); + } + return null; + } +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreValidateFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreValidateFilter.java index f41f8522..41999b66 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreValidateFilter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreValidateFilter.java @@ -1,7 +1,6 @@ package com.gitee.sop.gatewaycommon.zuul.filter; import com.gitee.sop.gatewaycommon.exception.ApiException; -import com.gitee.sop.gatewaycommon.manager.ParameterFormatter; import com.gitee.sop.gatewaycommon.param.ApiParam; import com.gitee.sop.gatewaycommon.param.ParamBuilder; import com.gitee.sop.gatewaycommon.validate.Validator; @@ -20,9 +19,6 @@ public class PreValidateFilter extends BaseZuulFilter { @Autowired private ParamBuilder paramBuilder; - @Autowired(required = false) - private ParameterFormatter parameterFormatter; - @Autowired private Validator validator; @@ -44,10 +40,6 @@ public class PreValidateFilter extends BaseZuulFilter { // 验证操作,这里有负责验证签名参数 try { validator.validate(param); - // 校验成功后进行参数转换 - if (parameterFormatter != null) { - parameterFormatter.format(param, requestContext); - } } catch (ApiException e) { log.error("验证失败,ip:{}, params:{}", param.fetchIp(), param.toJSONString(), e); throw e; diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParameterFormatter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParameterFormatter.java new file mode 100644 index 00000000..23885acd --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParameterFormatter.java @@ -0,0 +1,10 @@ +package com.gitee.sop.gatewaycommon.zuul.param; + +import com.alibaba.fastjson.JSONObject; +import com.gitee.sop.gatewaycommon.manager.ParameterFormatter; + +/** + * @author tanghc + */ +public interface ZuulParameterFormatter extends ParameterFormatter { +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/BaseParameterFormatter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParameterUtil.java similarity index 63% rename from sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/BaseParameterFormatter.java rename to sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParameterUtil.java index 24941c84..d8e29c8d 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/BaseParameterFormatter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParameterUtil.java @@ -1,13 +1,10 @@ package com.gitee.sop.gatewaycommon.zuul.param; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.gitee.sop.gatewaycommon.bean.SopConstants; -import com.gitee.sop.gatewaycommon.manager.ParameterFormatter; -import com.gitee.sop.gatewaycommon.param.ApiParam; import com.gitee.sop.gatewaycommon.util.RequestUtil; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import com.netflix.zuul.context.RequestContext; -import com.netflix.zuul.exception.ZuulException; import com.netflix.zuul.http.HttpServletRequestWrapper; import com.netflix.zuul.http.ServletInputStreamWrapper; import lombok.extern.slf4j.Slf4j; @@ -19,6 +16,7 @@ import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; import org.springframework.http.converter.FormHttpMessageConverter; import org.springframework.util.MultiValueMap; +import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.commons.CommonsMultipartResolver; import javax.servlet.ServletInputStream; @@ -29,30 +27,55 @@ import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Consumer; +import java.util.stream.Collectors; /** + * zuul参数工具 * @author tanghc */ @Slf4j -public abstract class BaseParameterFormatter implements ParameterFormatter { - - private FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter(); - - public void formatParams(ApiParam apiParam, RequestContext requestContext) throws ZuulException { - this.format(apiParam, requestContext); +public class ZuulParameterUtil { + + private static FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter(); + + /** + * 格式化参数 + * @param apiParam 请求的参数 + * @param consumer 修改参数 + * @param 参数类型 + */ + public static > void format(T apiParam, Consumer consumer) { + RequestContext requestContext = RequestContext.getCurrentContext(); + consumer.accept(apiParam); HttpServletRequest request = requestContext.getRequest(); String contentType = request.getContentType(); if (StringUtils.containsIgnoreCase(contentType, MediaType.APPLICATION_JSON_VALUE)) { - byte[] bytes = apiParam.toJSONString().getBytes(StandardCharsets.UTF_8); + String json = (apiParam instanceof JSONObject) ? + ((JSONObject) apiParam).toJSONString() + : JSON.toJSONString(apiParam); + byte[] bytes = json.getBytes(StandardCharsets.UTF_8); requestContext.setRequest(new ChangeParamsHttpServletRequestWrapper(request, bytes)); } else if(StringUtils.containsIgnoreCase(contentType, MediaType.APPLICATION_FORM_URLENCODED_VALUE)) { - List list = Lists.newArrayList(); + List list = new ArrayList<>(apiParam.size()); try { for (Map.Entry entry : apiParam.entrySet()) { - list.add(entry.getKey() + "=" + URLEncoder.encode(String.valueOf(entry.getValue()), SopConstants.UTF8)); + String key = entry.getKey(); + Object value = entry.getValue(); + if (value instanceof Collection) { + Collection collection = (Collection) value; + for (Object el : collection) { + list.add(key + "=" + URLEncoder.encode(String.valueOf(el), SopConstants.UTF8)); + } + } else { + list.add(key + "=" + URLEncoder.encode(String.valueOf(value), SopConstants.UTF8)); + } } } catch (UnsupportedEncodingException e) { log.error("字符集不支持", e); @@ -64,12 +87,19 @@ public abstract class BaseParameterFormatter implements ParameterFormatter builder = RequestContentDataExtractor.extract(request); for (Map.Entry entry : apiParam.entrySet()) { - builder.put(entry.getKey(), Collections.singletonList(String.valueOf(entry.getValue()))); + Object value = entry.getValue(); + if (value instanceof List) { + builder.put(entry.getKey(), (List)value); + } else { + builder.put(entry.getKey(), Collections.singletonList(String.valueOf(value))); + } } MediaType mediaType = MediaType.valueOf(request.getContentType()); // 将字段以及上传文件重写写入到流中 @@ -84,9 +114,15 @@ public abstract class BaseParameterFormatter implements ParameterFormatter> newParams = Maps.newHashMap(); + Map> newParams = new HashMap<>(); for (Map.Entry entry : apiParam.entrySet()) { - newParams.put(entry.getKey(), Collections.singletonList(String.valueOf(entry.getValue()))); + Object value = entry.getValue(); + if (value instanceof List) { + List valueList = ((List) value).stream().map(String::valueOf).collect(Collectors.toList()); + newParams.put(entry.getKey(), valueList); + } else { + newParams.put(entry.getKey(), Collections.singletonList(String.valueOf(value))); + } } requestContext.setRequestQueryParams(newParams); } @@ -143,4 +179,5 @@ public abstract class BaseParameterFormatter implements ParameterFormatter