我编写了以下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()
方法。
为什么不起作用,我该怎么办?
答案 0 :(得分:8)
我正在调用的服务(在本例中为Atlassian的Jira Cloud API)支持基本身份验证和OAuth身份验证。我试图使用HTTP Basic,但它会发回OAuth的身份验证质询。
从当前的JDK 11开始,HttpClient不会发送基本凭据,直到使用来自服务器的WWW-Authenticate标头对其进行质询为止。此外,它了解的唯一挑战类型是基本身份验证。如果您想看看,The relevant JDK code is here(与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());
}