Java 11 HttpClient not sending basic authentication

喜夏-厌秋 提交于 2021-02-07 05:21:13

问题


I wrote the following HttpClient code, and it did not result in an Authorization header being sent to the server:

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();
}

I'm getting an HTTP 401 error from the service I'm calling. In my case, it's the Atlassian Jira Cloud API.

I have confirmed that my getPasswordAuthentication() method is not being invoked by HttpClient.

Why isn't it working, and what should I do instead?


回答1:


The service I was calling (in this case, Atlassian's Jira Cloud API) supports both Basic and OAuth authentication. I was attempting to use HTTP Basic, but it sends back an auth challenge for OAuth.

As of the current JDK 11, HttpClient does not send Basic credentials until challenged for them with a WWW-Authenticate header from the server. Further, the only type of challenge it understands is for Basic authentication. The relevant JDK code is here (complete with TODO for supporting more than Basic auth) if you'd like to take a look.

In the meantime, my remedy has been to bypass HttpClient's authentication API and to create and send the Basic Authorization header myself:

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());
}


来源:https://stackoverflow.com/questions/54208945/java-11-httpclient-not-sending-basic-authentication

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!