溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Springcloud中zuul的過濾頭部是什么

發(fā)布時間:2021-10-19 17:24:15 來源:億速云 閱讀:175 作者:柒染 欄目:大數(shù)據(jù)

今天就跟大家聊聊有關Springcloud中zuul的過濾頭部是什么,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據(jù)這篇文章可以有所收獲。

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

    在使用zuul時,我有倆個需求,一是不讓zuul過濾頭部的Cookie,二是要在zuul網(wǎng)關對request的header設置requestId——便于鏈路追蹤。

    在網(wǎng)上搜了下,發(fā)現(xiàn)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<String> ignoredHeaders = new LinkedHashSet<>();
    ...
    private Set<String> sensitiveHeaders = new LinkedHashSet<>(
			Arrays.asList("Cookie", "Set-Cookie", "Authorization"));
    ...

    來看PreDecorationFilter的run方法實現(xiàn),如下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<String>());
    }
    @SuppressWarnings("unchecked")
    Set<String> set = (Set<String>) 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處,將方法上的參數(shù)值全部加入到HashSet中。

  3. 這樣,我們設置的sensitiveHeaders和ignoredHeaders全部加到HashSet中,需要注意的是1處和2處都調用了toLowerCase()方法,所以下游收到的header中的字段key都是小寫的。

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

    List-5

@Override
public 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<String, String> headers = this.helper
            .buildZuulRequestHeaders(request);
    ...
}

    List-6

public MultiValueMap<String, String> buildZuulRequestHeaders(
        HttpServletRequest request) {
    RequestContext context = RequestContext.getCurrentContext();
    MultiValueMap<String, String> headers = new HttpHeaders();
    Enumeration<String> headerNames = request.getHeaderNames();
    if (headerNames != null) {
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            if (isIncludedHeader(name)) {//1
                Enumeration<String> values = request.getHeaders(name);
                while (values.hasMoreElements()) {
                    String value = values.nextElement();
                    headers.add(name, value);
                }
            }
        }
    }
    Map<String, String> 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的過濾頭部是什么有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI