Java 11 HttpClient 不发送基本身份验证

2022-09-02 02:51:42

我编写了以下 HttpClient 代码,但它没有导致标头被发送到服务器:Authorization

public static void main(String[] args) {
    var client = HttpClient.newBuilder()
            .authenticator(new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication("username", "password".toCharArray());
                }
            })
            .version(HttpClient.Version.HTTP_1_1)
            .build();
    var request = HttpRequest.newBuilder()
            .uri("https://service-that-needs-auth.example/")
            .build();
    client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
            .thenApply(HttpResponse::body)
            .thenAccept(System.out::println)
            .join();
}

我从调用的服务收到 HTTP 401 错误。在我的情况下,它是Atlassian Jira Cloud API。

我已经确认我的方法没有被HttpClient调用。getPasswordAuthentication()

为什么它不起作用,我该怎么办?


答案 1

我调用的服务(在本例中为 Atlassian 的 Jira Cloud API)同时支持 Basic 和 OAuth 身份验证。我试图使用HTTP Basic,但它发回了OAuth的身份验证质询。

从当前的 JDK 11 开始,HttpClient 不会发送基本凭据,直到使用来自服务器的 WWW-Authenticate 标头为它们提出质询。此外,它理解的唯一质询类型是基本身份验证。相关的JDK代码在这里(配有TODO,支持比基本身份验证更多的功能),如果你想看一看的话。

与此同时,我的补救措施是绕过HttpClient的身份验证API,自己创建并发送基本授权标头:

public static void main(String[] args) {
    var client = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_1_1)
            .build();
    var request = HttpRequest.newBuilder()
            .uri(new URI("https://service-that-needs-auth.example/"))
            .header("Authorization", basicAuth("username", "password"))
            .build();
    client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
            .thenApply(HttpResponse::body)
            .thenAccept(System.out::println)
            .join();
}

private static String basicAuth(String username, String password) {
    return "Basic " + Base64.getEncoder().encodeToString((username + ":" + password).getBytes());
}

答案 2

推荐