千家信息网

Springcloud中zuul的过滤头部是什么

发表于:2025-02-02 作者:千家信息网编辑
千家信息网最后更新 2025年02月02日,今天就跟大家聊聊有关Springcloud中zuul的过滤头部是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Springcloud的版本
千家信息网最后更新 2025年02月02日Springcloud中zuul的过滤头部是什么

今天就跟大家聊聊有关Springcloud中zuul的过滤头部是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

Springcloud的版本是Greenwich.SR2,Springboot版本是2.1.6.release.

在使用zuul时,我有俩个需求,一是不让zuul过滤头部的Cookie,二是要在zuul网关对request的header设置requestId--便于链路追踪。

在网上搜了下,发现sensitiveHeaders和ignoredHeaders描述的较多,但是大多描述的不是较详细,同时自己也想知道底层上是如何做的,所以看了下源码,记录下。如下List-1,在application.yml中设置zuul的sensitiveHeaders和ignoredHeaders,先来说结论,sensitiveHeaders的值设置为x1后servletRequest header的x1不会传到下游;ignoredHeaders的值设置为x2后,servletRequest header的x2不会传到下游。

List-1

zuul:  sensitiveHeaders: x1  ignoredHeaders: x2

如下List-2所示,List-1中的配置会被Spring解析到ZuulProperties,sensitiveHeaders是有默认值的,即Cookie、Set-Cookie、Authorization。

List-2

@ConfigurationProperties("zuul")public class ZuulProperties {    ...    private Set ignoredHeaders = new LinkedHashSet<>();    ...    private Set sensitiveHeaders = new LinkedHashSet<>(                        Arrays.asList("Cookie", "Set-Cookie", "Authorization"));    ...

来看PreDecorationFilter的run方法实现,如下List-3,1处和2处,会将ZuulProperties中sensitiveHeaders的值加入到要过滤的字段里面,来看下ProxyRequestHelper的addIgnoredHeaders方法,如下List-4所示,RequestContext是个ConcurrentHashMap,

List-3

public class PreDecorationFilter extends ZuulFilter {    ...        @Override        public Object run() {                RequestContext ctx = RequestContext.getCurrentContext();                final String requestURI = this.urlPathHelper                                .getPathWithinApplication(ctx.getRequest());                Route route = this.routeLocator.getMatchingRoute(requestURI);                if (route != null) {                        String location = route.getLocation();                        if (location != null) {                                ctx.put(REQUEST_URI_KEY, route.getPath());                                ctx.put(PROXY_KEY, route.getId());                                if (!route.isCustomSensitiveHeaders()) {                                        this.proxyRequestHelper.addIgnoredHeaders(//1                                                        this.properties.getSensitiveHeaders().toArray(new String[0]));                                }                                else {                                        this.proxyRequestHelper.addIgnoredHeaders(//2                                                        route.getSensitiveHeaders().toArray(new String[0]));                                }        ...        }

List-4

public void addIgnoredHeaders(String... names) {    RequestContext ctx = RequestContext.getCurrentContext();    if (!ctx.containsKey(IGNORED_HEADERS)) {        ctx.set(IGNORED_HEADERS, new HashSet());    }    @SuppressWarnings("unchecked")    Set set = (Set) ctx.get(IGNORED_HEADERS);    for (String name : this.ignoredHeaders) {        set.add(name.toLowerCase());//1    }    for (String name : names) {        set.add(name.toLowerCase());//2    }}
  1. List-4中,1处this.ignoredHeaders()会获取ZuulProperties中的ignoredHeaders,之后加入到HashSet中。

  2. 2处,将方法上的参数值全部加入到HashSet中。

  3. 这样,我们设置的sensitiveHeaders和ignoredHeaders全部加到HashSet中,需要注意的是1处和2处都调用了toLowerCase()方法,所以下游收到的header中的字段key都是小写的。

来看RibbonRoutingFilter的run方法,如下List-5,run()调用buildCommandContext来构造RibbonCommand,buildCommandContext方法中调用了ProxyRequestHelper的buildZuulRequestHeaders方法,如List-6所示。

List-5

@Overridepublic Object run() {    RequestContext context = RequestContext.getCurrentContext();    this.helper.addIgnoredHeaders();    try {        RibbonCommandContext commandContext = buildCommandContext(context);        ClientHttpResponse response = forward(commandContext);        setResponse(response);        return response;    ...}protected RibbonCommandContext buildCommandContext(RequestContext context) {    HttpServletRequest request = context.getRequest();    MultiValueMap headers = this.helper            .buildZuulRequestHeaders(request);    ...}

List-6

public MultiValueMap buildZuulRequestHeaders(        HttpServletRequest request) {    RequestContext context = RequestContext.getCurrentContext();    MultiValueMap headers = new HttpHeaders();    Enumeration headerNames = request.getHeaderNames();    if (headerNames != null) {        while (headerNames.hasMoreElements()) {            String name = headerNames.nextElement();            if (isIncludedHeader(name)) {//1                Enumeration values = request.getHeaders(name);                while (values.hasMoreElements()) {                    String value = values.nextElement();                    headers.add(name, value);                }            }        }    }    Map zuulRequestHeaders = context.getZuulRequestHeaders();    for (String header : zuulRequestHeaders.keySet()) {        if (isIncludedHeader(header)) {//2            headers.set(header, zuulRequestHeaders.get(header));        }    }    if (!headers.containsKey(HttpHeaders.ACCEPT_ENCODING)) {        headers.set(HttpHeaders.ACCEPT_ENCODING, "gzip");    }    return headers;}public boolean isIncludedHeader(String headerName) {    String name = headerName.toLowerCase();    RequestContext ctx = RequestContext.getCurrentContext();    if (ctx.containsKey(IGNORED_HEADERS)) {        Object object = ctx.get(IGNORED_HEADERS);        if (object instanceof Collection && ((Collection) object).contains(name)) {            return false;        }    }    switch (name) {    case "host":        if (addHostHeader) {            return true;        }    case "connection":    case "content-length":    case "server":    case "transfer-encoding":    case "x-application-context":        return false;    default:        return true;    }}
  1. 获取HttpServletRequest的header,之后遍历,调用isIncludedHeader方法,isIncludedHeader里面获取RequestContext,判断当前的这个header key是不是在IGNORED_HEADERS这个集合里面--List-4中设置的,如果在里面,那么返回false,不会将这个header字段往下游传。

  2. 2处,context.getZuulRequestHeaders()获取我们手动设置的header(调用addZuulResponseHeader方法设置),之后逐个遍历,如果在IGNORED_HEADERS这个集合里面--List-4中,则不会加入到headers中,即不往下游传。

注:链路为什么从PreDecorationFilter到RibbonRoutingFilter的,这和Zuul的内部的ZuulFilter机制有关。

要注意的是,如果要往下游传的header含有大写的,那么下游接收到的header是小写的,原因在List-4中可以看出。

看完上述内容,你们对Springcloud中zuul的过滤头部是什么有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注行业资讯频道,感谢大家的支持。

0