Spring-cloud-gateway:请求超过30个标头时使用HTTP400

时间:2019-09-17 15:22:47

标签: spring-cloud spring-cloud-gateway

我将spring-cloud-gateway用作API网关,该网关位于负责预身份验证(单点登录)的apache层后面。这一层将一堆标题添加到我的spring-cloud-gateway应用程序的传入请求中,并且当此数目超过30个时。我从网关获得了HTTP 400响应。

我有一个自定义过滤器,该过滤器与后端用户服务对话以执行强制授权。此过滤器会向交易所的请求添加更多标头。

HttpHeaders headers = new HttpHeaders();
headers.setContentType(APPLICATION_JSON);
headers.set(PRINCIPAL, userId);
HttpEntity<Void> responseType = new HttpEntity<Void>(headers);
ResponseEntity<UserDto> response = restTemplate.exchange(CURRENT_USER_ENDPOINT, HttpMethod.GET, responseType, UserDto.class);
addUserDetailsToHeaders(exchange, response.getBody());

由于某种原因,此过滤器对任何包含30个以上标头的网关请求造成干扰 当显示> 30个标头时,我从网关获得的响应正文如下。

<html>
  <head>
    <title>Bad Request</title>
  </head>
  <body>
    <h1><p>Bad Request</p></h1>
    Error parsing headers: &#x27;limit request headers fields&#x27;
  </body>
</html>

我可以使用curl在本地运行网关时模拟问题。例如:

curl 'http://localhost:8080/my-api-app/' -H 'Connection: keep-alive' -H 'Cache-Control: max-age=0' -H 'Upgrade-Insecure-Requests: 1' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36' -H 'Sec-Fetch-Mode: navigate' -H 'Sec-Fetch-User: ?1' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3' -H 'Sec-Fetch-Site: none' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: en-GB,en;q=0.9,en-US;q=0.8,ja;q=0.7' -H 'Cookie: 567583457' -H 'uid: 1234567' -H 'employee: N' -H 'x-forwarded-proto: https' -H 'x-forwarded-for: 10.45.67.65, 172.16.8.1' -H 'X-Forwarded-Host: xxxxxxxxxxxxxxx' -H 'X-Forwarded-Server: xxxxxxxxxxxxx' -H 'Ct_request_id: 11' -H 'managername: xxxxxxxx, xxxxx'  -H 'Ctscuserkeywords: NotExpired,PasswordPolicy' -H 'Destinationindicator: IE' -H 'a: b' -H 'c: d' -H 'derek: test'  --compressed

我可以使用spring-cloud-gateway-sample项目通过弯曲此曲线来模拟同样的400个响应(因此实际极限看起来像90)

curl 'http://localhost:8080/get' -H 'key1: val' -H 'key2: val' -H 'key3: val' -H 'key4: val' -H 'key5: val' -H 'key6: val' -H 'key7: val' -H 'key8: val' -H 'key9: val' -H 'key10: val' -H 'key11: val' -H 'key12: val' -H 'key13: val' -H 'key14: val' -H 'key15: val' -H 'key16: val' -H 'key17: val' -H 'key18: val' -H 'key19: val' -H 'key20: val' -H 'key21: val' -H 'key22: val' -H 'key23: val' -H 'key24: val' -H 'key25: val' -H 'key26: val' -H 'key27: val' -H 'key28: val' -H 'key29: val' -H 'key30: val' -H 'key31: val' -H 'key32: val' -H 'key33: val' -H 'key34: val' -H 'key35: val' -H 'key36: val' -H 'key37: val' -H 'key38: val' -H 'key39: val' -H 'key40: val' -H 'key41: val' -H 'key42: val' -H 'key43: val' -H 'key44: val' -H 'key45: val' -H 'key46: val' -H 'key47: val' -H 'key48: val' -H 'key49: val' -H 'key50: val' -H 'key51: val' -H 'key52: val' -H 'key53: val' -H 'key54: val' -H 'key55: val' -H 'key56: val' -H 'key57: val' -H 'key58: val' -H 'key59: val' -H 'key60: val' -H 'key61: val' -H 'key62: val' -H 'key63: val' -H 'key64: val' -H 'key65: val' -H 'key66: val' -H 'key67: val' -H 'key68: val' -H 'key69: val' -H 'key70: val' -H 'key71: val' -H 'key72: val' -H 'key73: val' -H 'key74: val' -H 'key75: val' -H 'key76: val' -H 'key77: val' -H 'key78: val' -H 'key79: val' -H 'key80: val' -H 'key81: val' -H 'key82: val' -H 'key83: val' -H 'key84: val' -H 'key85: val' -H 'key86: val' -H 'key87: val' -H 'key88: val' -H 'key89: val' -H 'key90: val' -H 'key91: val'

2 个答案:

答案 0 :(得分:1)

问题原来是cloudfoundry的cf路由器拒绝了该请求。网关没问题。令人困惑的是,cf路由器返回400时未添加任何响应标头。

我有一个自定义过滤器,其中添加了一个特殊的标头,其中包含一个用逗号分隔的列表,该列表很长(200至300个字符)。我减少了长度,然后奏效了。

答案 1 :(得分:0)

您是否正在使用嵌入式Tomcat?

查看有关此问题的这篇文章:https://thewebspark.com/2017/12/06/tomcat-request-header-too-large-resolved/

  

要解决此错误,请检查发出的请求是GET还是POST?

     

如果它是GET请求,然后将其更改为HTTP POST,则在大多数情况下,由于URL长度超过2000个字符,该错误将得到解决。在这种情况下,最好使用POST或拆分URL。

     

maxHttpHeaderSize:请求和响应HTTP标头的最大大小,以字节为单位。如果未指定,则此属性设置为4096(4 KB)。

     

您将在

中找到它      

$ TOMCAT_HOME / conf / server.xml

     

在server.xml中,更改HTTP / 1.1连接器条目,并将maxHttpHeaderSize设置为“ 65536”(64Kb字节),如下所示:

     

连接器端口=“ 8080” maxHttpHeaderSize =“ 65536”协议=“ HTTP / 1.1” ...

如果使用嵌入式Tomcat,请尝试对其进行配置以增加最大标头的大小: https://www.baeldung.com/spring-boot-configure-tomcat

如果不使用Embedded Tomcat,我也在Pivotal的同一主题上发现了这一点:https://community.pivotal.io/s/article/spring-boot-app-rejects-http-request-with-total-header-size-larger-than-8kb