【发布时间】:2023-03-11 22:15:01
【问题描述】:
我使用 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: 'limit request headers fields'
</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 项目通过这个 curl 来模拟相同的 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'
【问题讨论】:
-
我插入了 curl 命令,它对我来说很好用。你用的是什么版本?您确定错误来自网关而不是下游应用程序吗?
-
Spencer,是的,我 100% 确定它来自网关。我什至写了一个特殊的下游 python 应用程序来记录所有请求,它永远不会被命中。我确实有一些自定义过滤器。还连接了一个 Eureka 发现客户端。我正在使用 Greenwich.SR2。有趣的是,请求确实通过了我的 3 个过滤器
-
我无法复制它。能否提供一个示例项目?
-
斯宾塞,谢谢。原来这是我的自定义过滤器之一。我的自定义过滤器正在与另一个服务交谈以获取用户详细信息(授权),并且由于某种原因,这干扰了通过过滤器链的请求。在我的自定义过滤器中,我使用的是 Spring 的 restTemplate.exchange(....)。我认为如果我现在用更多细节更新问题会更好......在这里很难适应所有细节
-
我更新了问题。我能够通过点击具有 > 90 个标题的 spring-cloud-sample 应用程序来重现它。我知道这是不切实际的,但我对位于我们的 PCF 实例前面的层的控制有限,它正在添加大量标题。
标签: spring-cloud spring-cloud-gateway