gpt4 book ai didi

java - 来自使用 Java 11 和 Spring Boot 的 java.net.http.HttpClient 调用的不可靠响应

转载 作者:行者123 更新时间:2023-12-04 09:29:57 25 4
gpt4 key购买 nike

我正在 Spring Boot 中编写一个后端应用程序,它从第三方调用另一个 API。
我遇到了这个特定调用的问题,它检索一个包含不记名 token 的 token 对象,然后我在他们的其他端点中使用它。
在调用其他端点时,检索到的 token 有时会起作用,但大多数时候不起作用,从而导致未经授权的响应。

@RestController
public class CotizacionController {

Logger logger = LoggerFactory.getLogger(CotizacionController.class);

@Value("${service.credentials.tokenServer}")
private String tokenServer;

@Value("${service.credentials.grantType}")
private String grantType;

@Value("${service.credentials.username}")
private String username;

@Value("${service.credentials.password}")
private String password;

HttpClient client = HttpClient.newHttpClient();

@RequestMapping("/create")
public Object Create() throws IOException, InterruptedException {

HashMap<String, String> parameters = new HashMap<>();
parameters.put("grant_type", grantType);
parameters.put("username", username);
parameters.put("password", password);

String form = parameters.keySet().stream()
.map(key -> key + "="
+ URLEncoder.encode(parameters.get(key),
StandardCharsets.UTF_8))
.collect(Collectors.joining("&"));

HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(tokenServer))
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(BodyPublishers.ofString(form)).build();

HttpResponse<?> response = client.send(request, BodyHandlers.ofString());

TokenResponse result = new ObjectMapper().readValue(response
.body().toString(), TokenResponse.class);

return result;
}

}
这是一个示例 token 对象:
{
"access_token": "z-bu-Pde6M2dlPiaRzd5XpTrT7ohpFQZe157HHVLfdKJWsdmKCloK7AYGEw7SLCe28tjYAxo8MZOE_3W00HEa-bqgUvcrAKfxIubAq0UGXv7jLPWbRwWzhAUCDon3kdstUrJ_OKRN2y26W6qyDBGDqlP5NRSF4unH_pD_ShmpDlSxZdYUqD0da5Y2_uO6YRs5GuWA7XhI9sPa98SxuXN_dwiDJVif418xK646fUgWR8",
"token_type": "bearer",
"expires_in": "3599"
}
使用 检索 token postman 工作得很好 ,所以这不可能是第三方 API 的问题。我也有这个 在 .NET Core 3 中实现的相同服务,它也能正常工作 在那边。
最让我困惑的是实际的 HttpClient 调用有效,我确实得到了一个正确的 Json,它映射到我的 TokenResponse 对象就好了。只是 token 值无效......有时。
我也尝试过使用 RestTemplate 和 WebClient Spring 库,但结果是一样的。调用有效,但检索到的 token 无效。
起初我以为我遇到了竞争条件,因为最初我有另一个 HttpClient 和另一个端点使用 token 调用的响应。所以我将其简化为仅 token 调用并手动将 token 值复制到 postman 请求中。没用。
然后我想也许我的 HttpClient 授权 header 格式不正确,但这是不正确的,因为简单地使用 postman 请求将 token 复制到 protected 端点表明 token 不起作用。
以及我尝试过的其他事情:
  • 将我在 Controller 中生成的表单字符串粘贴到 Postman 请求中以确保它有效。
  • 检查 URLEncoder 是否没有弄乱任何表单值。
  • 复制 token 对象中的 token 值以在 Postman 的另一个端点中使用。
  • 跳过对象映射并返回一个简单的字符串,然后从 Postman 的响应中手动复制 token 值,以便我可以在另一个端点中使用它。

  • 在这一点上我很迷茫,唯一想到的是 HttpClient.send() 方法可能正在以可能影响内容的方式解析正文?我对此表示怀疑,但我不知道还会发生什么。

    最佳答案

    解决方案与cookie有关!
    token 服务器响应正在发送 2 set-cookie Postman 和 .NET Core 中的 header 被自动处理并设置为后续的 HTTP 请求。
    第 3 方 API 位于负载均衡器的后面并生成这些 session cookie。
    我通过实现系统范围的 CookieHandler 解决了这个问题在我的 main 中使用以下代码方法。

    public static void main(String[] args) {
    CookieHandler.setDefault(new CookieManager());

    SpringApplication.run(Main.class, args);
    }
    然后像这样构建我的 HttpClient 对象:
    ...
    HttpClient client = HttpClient.newBuilder().cookieHandler(CookieHandler.getDefault()).build();
    ...
    这样,回复 set-cookie并请求 cookie header 将自动处理并在此 HttpClient 进行的所有调用中工作。
    默认情况下,CookieHandler 是用 CookiePolicy.ACCEPT_ORIGINAL_SERVER 创建的。范围。我的理解是,只有当 cookie 由同一主机设置和请求时,这才会使 cookie 工作。查看文档以获取更多选项 CookiePolicy

    关于java - 来自使用 Java 11 和 Spring Boot 的 java.net.http.HttpClient 调用的不可靠响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62887967/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com