【问题标题】:HTTP Authentication - Java Http Client is missing header that is present via curlHTTP 身份验证 - Java Http 客户端缺少通过 curl 存在的标头
【发布时间】:2026-02-11 23:00:01
【问题描述】:

我正在尝试使用 java.net.http.HttpClient 向 HTTP 端点发送一个简单的 GET。端点需要基本身份验证。很简单,我正在做每个人都在做的事情:

HttpClient httpClient = HttpClient.newBuilder()
                                  .version(HttpClient.Version.HTTP_1_1)
                                  .authenticator(new Authenticator(){
                                    @Override
                                    protected PasswordAuthentication getPasswordAuthentication() {
                                      return new PasswordAuthentication("guest","guest".toCharArray());
                                    }
                                   })
                                  .build();
HttpRequest request = HttpRequest.newBuilder()
                                 .GET()
                                 .uri(URI.create("localhost:15672/api/overview")
                                 .build();
HttpResponse<Void> httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.discarding());

但是,这会引发 IOException“缺少响应代码 401 的 WWW-Authenticate 标头”。服务器最初以 401 响应,然后客户端在 Authenticator 的帮助下重新尝试请求,这对我来说并非完全不合理。标头是强制性的,如果不存在,则需要例外。

到目前为止,一切都很好。但是,当我通过 curl 执行相同的请求时,标头 is 存在:

> curl -i http://localhost:15672/api/overview
HTTP/1.1 401 Unauthorized
content-length: 0
content-security-policy: script-src 'self' 'unsafe-eval' 'unsafe-inline'; object-src 'self'
date: Thu, 08 Jul 2021 11:06:45 GMT
server: Cowboy
vary: origin
www-authenticate: Basic realm="RabbitMQ Management"

我在这里做错了什么?

【问题讨论】:

    标签: java http-headers http-status-code-401 java-http-client


    【解决方案1】:

    与此同时,我发现了问题所在:我正在联系的服务器有问题。第一个 GET 准确地返回了显示为 curl 结果的内容。 Java HttpClient 正确响应并发送了第二个带有凭据的 GET。凭据错误(出于测试目的),但响应不是预期的 403,而是另一个 401,而第二个 401 响应是缺少标头的响应。

    【讨论】:

      【解决方案2】:

      基本授权可以做

      String plainCreds = "myuser:mypassword";
      byte[] base64Bytes = Base64.encodeBase64(plainCreds.getBytes());
      
      HttpRequest request = HttpRequest.newBuilder()
         .get()
         .uri(URI.create("localhost:15672/api/overview"))
         .header("Authorization", "Basic " + new String(base64Bytes))
         .build();
      

      【讨论】:

      • 我知道,但我想知道为什么我的方法不起作用。如果我理解正确,Java Http Client 应该会自动执行此操作。它也没有解释为什么我会收到异常。
      • 我相信你应该使用BasicCredentialsProvider而不是PasswordAuthentication
      • 那是 Apache HttpClient 的,不是 JDK 的