NTLM scheme deprecated and disabled by default
This commit is contained in:
parent
8aa4fbc8de
commit
83c6079e65
|
@ -30,7 +30,6 @@ The JAR packages can be found in the target folders of their respective modules
|
||||||
httpclient5/target/httpclient5-<VERSION>.jar
|
httpclient5/target/httpclient5-<VERSION>.jar
|
||||||
httpclient5-cache/target/httpclient5-cache-<VERSION>.jar
|
httpclient5-cache/target/httpclient5-cache-<VERSION>.jar
|
||||||
httpclient5-fluent/target/httpclient5-fluent-<VERSION>.jar
|
httpclient5-fluent/target/httpclient5-fluent-<VERSION>.jar
|
||||||
httpclient5-win/target/httpclient5-win-<VERSION>.jar
|
|
||||||
httpclient5-osgi/target/org.apache.httpcomponents.httpclient_<VERSION>.jar
|
httpclient5-osgi/target/org.apache.httpcomponents.httpclient_<VERSION>.jar
|
||||||
|
|
||||||
where <VERSION> is the release version
|
where <VERSION> is the release version
|
||||||
|
|
|
@ -52,6 +52,7 @@ import org.apache.hc.core5.http.message.StatusLine;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class TestByteArrayCacheEntrySerializer {
|
public class TestByteArrayCacheEntrySerializer {
|
||||||
|
|
||||||
private ByteArrayCacheEntrySerializer impl;
|
private ByteArrayCacheEntrySerializer impl;
|
||||||
|
|
|
@ -33,7 +33,6 @@ import org.apache.hc.client5.http.auth.AuthCache;
|
||||||
import org.apache.hc.client5.http.auth.AuthScope;
|
import org.apache.hc.client5.http.auth.AuthScope;
|
||||||
import org.apache.hc.client5.http.auth.Credentials;
|
import org.apache.hc.client5.http.auth.Credentials;
|
||||||
import org.apache.hc.client5.http.auth.CredentialsStore;
|
import org.apache.hc.client5.http.auth.CredentialsStore;
|
||||||
import org.apache.hc.client5.http.auth.NTCredentials;
|
|
||||||
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
|
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
|
||||||
import org.apache.hc.client5.http.config.ConnectionConfig;
|
import org.apache.hc.client5.http.config.ConnectionConfig;
|
||||||
import org.apache.hc.client5.http.cookie.CookieStore;
|
import org.apache.hc.client5.http.cookie.CookieStore;
|
||||||
|
@ -186,10 +185,14 @@ public class Executor {
|
||||||
return auth(host, new UsernamePasswordCredentials(username, password));
|
return auth(host, new UsernamePasswordCredentials(username, password));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #auth(HttpHost, String, char[])}.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public Executor auth(final HttpHost host,
|
public Executor auth(final HttpHost host,
|
||||||
final String username, final char[] password,
|
final String username, final char[] password,
|
||||||
final String workstation, final String domain) {
|
final String workstation, final String domain) {
|
||||||
return auth(host, new NTCredentials(username, password, workstation, domain));
|
return auth(host, new org.apache.hc.client5.http.auth.NTCredentials(username, password, workstation, domain));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Executor clearAuth() {
|
public Executor clearAuth() {
|
||||||
|
|
|
@ -77,11 +77,6 @@
|
||||||
<artifactId>httpclient5-fluent</artifactId>
|
<artifactId>httpclient5-fluent</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
|
||||||
<artifactId>httpclient5-win</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit-jupiter-params</artifactId>
|
<artifactId>junit-jupiter-params</artifactId>
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
/*
|
|
||||||
* ====================================================================
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*
|
|
||||||
* This software consists of voluntary contributions made by many
|
|
||||||
* individuals on behalf of the Apache Software Foundation. For more
|
|
||||||
* information on the Apache Software Foundation, please see
|
|
||||||
* <http://www.apache.org/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.hc.client5.http.impl.win;
|
|
||||||
|
|
||||||
import com.sun.jna.platform.win32.Sspi;
|
|
||||||
import com.sun.jna.platform.win32.Win32Exception;
|
|
||||||
import com.sun.jna.platform.win32.WinError;
|
|
||||||
|
|
||||||
public final class WindowsNegotiateSchemeGetTokenFail extends WindowsNegotiateScheme {
|
|
||||||
|
|
||||||
public WindowsNegotiateSchemeGetTokenFail(final String schemeName, final String servicePrincipalName) {
|
|
||||||
super(schemeName, servicePrincipalName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
String getToken(final Sspi.CtxtHandle continueCtx, final Sspi.SecBufferDesc continueToken, final String targetName) {
|
|
||||||
dispose();
|
|
||||||
/* We will rather throw SEC_E_TARGET_UNKNOWN because SEC_E_DOWNGRADE_DETECTED is not
|
|
||||||
* available on Windows XP and this unit test always fails.
|
|
||||||
*/
|
|
||||||
throw new Win32Exception(WinError.SEC_E_TARGET_UNKNOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,261 +0,0 @@
|
||||||
/*
|
|
||||||
* ====================================================================
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*
|
|
||||||
* This software consists of voluntary contributions made by many
|
|
||||||
* individuals on behalf of the Apache Software Foundation. For more
|
|
||||||
* information on the Apache Software Foundation, please see
|
|
||||||
* <http://www.apache.org/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.hc.client5.testing.sync;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
import org.apache.hc.client5.http.auth.CredentialsProvider;
|
|
||||||
import org.apache.hc.client5.http.auth.NTCredentials;
|
|
||||||
import org.apache.hc.client5.http.auth.StandardAuthScheme;
|
|
||||||
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
|
||||||
import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
|
|
||||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
|
||||||
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
|
|
||||||
import org.apache.hc.client5.http.protocol.HttpClientContext;
|
|
||||||
import org.apache.hc.client5.testing.sync.extension.TestClientResources;
|
|
||||||
import org.apache.hc.core5.http.ClassicHttpRequest;
|
|
||||||
import org.apache.hc.core5.http.ClassicHttpResponse;
|
|
||||||
import org.apache.hc.core5.http.HttpException;
|
|
||||||
import org.apache.hc.core5.http.HttpHeaders;
|
|
||||||
import org.apache.hc.core5.http.HttpHost;
|
|
||||||
import org.apache.hc.core5.http.HttpStatus;
|
|
||||||
import org.apache.hc.core5.http.URIScheme;
|
|
||||||
import org.apache.hc.core5.http.io.HttpRequestHandler;
|
|
||||||
import org.apache.hc.core5.http.io.entity.EntityUtils;
|
|
||||||
import org.apache.hc.core5.http.protocol.HttpContext;
|
|
||||||
import org.apache.hc.core5.testing.classic.ClassicTestServer;
|
|
||||||
import org.apache.hc.core5.util.Timeout;
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unit tests for some of the NTLM auth functionality..
|
|
||||||
*/
|
|
||||||
public class TestClientAuthenticationFakeNTLM {
|
|
||||||
|
|
||||||
public static final Timeout TIMEOUT = Timeout.ofMinutes(1);
|
|
||||||
|
|
||||||
@RegisterExtension
|
|
||||||
private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT);
|
|
||||||
|
|
||||||
public ClassicTestServer startServer() throws IOException {
|
|
||||||
return testResources.startServer(null, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CloseableHttpClient startClient(final Consumer<HttpClientBuilder> clientCustomizer) {
|
|
||||||
return testResources.startClient(clientCustomizer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CloseableHttpClient startClient() {
|
|
||||||
return testResources.startClient(builder -> {});
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpHost targetHost() {
|
|
||||||
return testResources.targetHost();
|
|
||||||
}
|
|
||||||
|
|
||||||
static class NtlmResponseHandler implements HttpRequestHandler {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handle(
|
|
||||||
final ClassicHttpRequest request,
|
|
||||||
final ClassicHttpResponse response,
|
|
||||||
final HttpContext context) throws HttpException, IOException {
|
|
||||||
response.setCode(HttpStatus.SC_UNAUTHORIZED);
|
|
||||||
response.setHeader("Connection", "Keep-Alive");
|
|
||||||
response.setHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.NTLM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNTLMAuthenticationFailure() throws Exception {
|
|
||||||
final ClassicTestServer server = startServer();
|
|
||||||
server.registerHandler("*", new NtlmResponseHandler());
|
|
||||||
final HttpHost target = targetHost();
|
|
||||||
|
|
||||||
final CredentialsProvider credsProvider = CredentialsProviderBuilder.create()
|
|
||||||
.add(target, new NTCredentials("test", "test".toCharArray(), null, null))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
final CloseableHttpClient client = startClient(builder -> builder
|
|
||||||
.setDefaultCredentialsProvider(credsProvider)
|
|
||||||
);
|
|
||||||
|
|
||||||
final HttpContext context = HttpClientContext.create();
|
|
||||||
final HttpGet httpget = new HttpGet("/");
|
|
||||||
|
|
||||||
client.execute(target, httpget, context, response -> {
|
|
||||||
EntityUtils.consume(response.getEntity());
|
|
||||||
Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static class NtlmType2MessageResponseHandler implements HttpRequestHandler {
|
|
||||||
|
|
||||||
private final String authenticateHeaderValue;
|
|
||||||
|
|
||||||
public NtlmType2MessageResponseHandler(final String type2Message) {
|
|
||||||
this.authenticateHeaderValue = StandardAuthScheme.NTLM + " " + type2Message;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handle(
|
|
||||||
final ClassicHttpRequest request,
|
|
||||||
final ClassicHttpResponse response,
|
|
||||||
final HttpContext context) throws HttpException, IOException {
|
|
||||||
response.setCode(HttpStatus.SC_UNAUTHORIZED);
|
|
||||||
response.setHeader("Connection", "Keep-Alive");
|
|
||||||
if (!request.containsHeader(HttpHeaders.AUTHORIZATION)) {
|
|
||||||
response.setHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.NTLM);
|
|
||||||
} else {
|
|
||||||
response.setHeader(HttpHeaders.WWW_AUTHENTICATE, authenticateHeaderValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNTLMv1Type2Message() throws Exception {
|
|
||||||
final ClassicTestServer server = startServer();
|
|
||||||
server.registerHandler("*", new NtlmType2MessageResponseHandler("TlRMTVNTUAACAA" +
|
|
||||||
"AADAAMADgAAAAzggLiASNFZ4mrze8AAAAAAAAAAAAAAAAAAAAABgBwFwAAAA9T" +
|
|
||||||
"AGUAcgB2AGUAcgA="));
|
|
||||||
final HttpHost target = targetHost();
|
|
||||||
|
|
||||||
final CredentialsProvider credsProvider = CredentialsProviderBuilder.create()
|
|
||||||
.add(target, new NTCredentials("test", "test".toCharArray(), null, null))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
final CloseableHttpClient client = startClient(builder -> builder
|
|
||||||
.setDefaultCredentialsProvider(credsProvider)
|
|
||||||
);
|
|
||||||
|
|
||||||
final HttpContext context = HttpClientContext.create();
|
|
||||||
final HttpGet httpget = new HttpGet("/");
|
|
||||||
|
|
||||||
client.execute(target, httpget, context, response -> {
|
|
||||||
EntityUtils.consume(response.getEntity());
|
|
||||||
Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNTLMv2Type2Message() throws Exception {
|
|
||||||
final ClassicTestServer server = startServer();
|
|
||||||
server.registerHandler("*", new NtlmType2MessageResponseHandler("TlRMTVNTUAACAA" +
|
|
||||||
"AADAAMADgAAAAzgoriASNFZ4mrze8AAAAAAAAAACQAJABEAAAABgBwFwAAAA9T" +
|
|
||||||
"AGUAcgB2AGUAcgACAAwARABvAG0AYQBpAG4AAQAMAFMAZQByAHYAZQByAAAAAAA="));
|
|
||||||
final HttpHost target = targetHost();
|
|
||||||
|
|
||||||
final CredentialsProvider credsProvider = CredentialsProviderBuilder.create()
|
|
||||||
.add(target, new NTCredentials("test", "test".toCharArray(), null, null))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
final CloseableHttpClient client = startClient(builder -> builder
|
|
||||||
.setDefaultCredentialsProvider(credsProvider)
|
|
||||||
);
|
|
||||||
|
|
||||||
final HttpContext context = HttpClientContext.create();
|
|
||||||
final HttpGet httpget = new HttpGet("/");
|
|
||||||
|
|
||||||
client.execute(target, httpget, context, response -> {
|
|
||||||
EntityUtils.consume(response.getEntity());
|
|
||||||
Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static class NtlmType2MessageOnlyResponseHandler implements HttpRequestHandler {
|
|
||||||
|
|
||||||
private final String authenticateHeaderValue;
|
|
||||||
|
|
||||||
public NtlmType2MessageOnlyResponseHandler(final String type2Message) {
|
|
||||||
this.authenticateHeaderValue = StandardAuthScheme.NTLM + " " + type2Message;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handle(
|
|
||||||
final ClassicHttpRequest request,
|
|
||||||
final ClassicHttpResponse response,
|
|
||||||
final HttpContext context) throws HttpException, IOException {
|
|
||||||
response.setCode(HttpStatus.SC_UNAUTHORIZED);
|
|
||||||
response.setHeader("Connection", "Keep-Alive");
|
|
||||||
response.setHeader(HttpHeaders.WWW_AUTHENTICATE, authenticateHeaderValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNTLMType2MessageOnlyAuthenticationFailure() throws Exception {
|
|
||||||
final ClassicTestServer server = startServer();
|
|
||||||
server.registerHandler("*", new NtlmType2MessageOnlyResponseHandler("TlRMTVNTUAACAA" +
|
|
||||||
"AADAAMADgAAAAzggLiASNFZ4mrze8AAAAAAAAAAAAAAAAAAAAABgBwFwAAAA9T" +
|
|
||||||
"AGUAcgB2AGUAcgA="));
|
|
||||||
final HttpHost target = targetHost();
|
|
||||||
|
|
||||||
final CloseableHttpClient client = startClient();
|
|
||||||
|
|
||||||
final HttpClientContext context = HttpClientContext.create();
|
|
||||||
context.setCredentialsProvider(CredentialsProviderBuilder.create()
|
|
||||||
.add(target, new NTCredentials("test", "test".toCharArray(), null, null))
|
|
||||||
.build());
|
|
||||||
final HttpGet httpget = new HttpGet("/");
|
|
||||||
|
|
||||||
client.execute(target, httpget, context, response -> {
|
|
||||||
EntityUtils.consume(response.getEntity());
|
|
||||||
Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNTLMType2NonUnicodeMessageOnlyAuthenticationFailure() throws Exception {
|
|
||||||
final ClassicTestServer server = startServer();
|
|
||||||
server.registerHandler("*", new NtlmType2MessageOnlyResponseHandler("TlRMTVNTUAACAA" +
|
|
||||||
"AABgAGADgAAAAyggLiASNFZ4mrze8AAAAAAAAAAAAAAAAAAAAABgBwFwAAAA9T" +
|
|
||||||
"ZXJ2ZXI="));
|
|
||||||
final HttpHost target = targetHost();
|
|
||||||
|
|
||||||
|
|
||||||
final CloseableHttpClient client = startClient();
|
|
||||||
|
|
||||||
final HttpClientContext context = HttpClientContext.create();
|
|
||||||
context.setCredentialsProvider(CredentialsProviderBuilder.create()
|
|
||||||
.add(target, new NTCredentials("test", "test".toCharArray(), null, null))
|
|
||||||
.build());
|
|
||||||
final HttpGet httpget = new HttpGet("/");
|
|
||||||
|
|
||||||
client.execute(target, httpget, context, response -> {
|
|
||||||
EntityUtils.consume(response.getEntity());
|
|
||||||
Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -125,6 +125,7 @@ public class TestSPNegoScheme {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
private static class UseJaasCredentials implements Credentials {
|
private static class UseJaasCredentials implements Credentials {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
* ====================================================================
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*
|
|
||||||
* This software consists of voluntary contributions made by many
|
|
||||||
* individuals on behalf of the Apache Software Foundation. For more
|
|
||||||
* information on the Apache Software Foundation, please see
|
|
||||||
* <http://www.apache.org/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.hc.client5.testing.sync;
|
|
||||||
|
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
|
||||||
|
|
||||||
import org.apache.hc.client5.http.auth.AuthSchemeFactory;
|
|
||||||
import org.apache.hc.client5.http.auth.StandardAuthScheme;
|
|
||||||
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
|
||||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
|
||||||
import org.apache.hc.client5.http.impl.win.WinHttpClients;
|
|
||||||
import org.apache.hc.client5.http.impl.win.WindowsNegotiateSchemeGetTokenFail;
|
|
||||||
import org.apache.hc.client5.testing.sync.extension.TestClientResources;
|
|
||||||
import org.apache.hc.core5.http.HttpHeaders;
|
|
||||||
import org.apache.hc.core5.http.HttpHost;
|
|
||||||
import org.apache.hc.core5.http.HttpStatus;
|
|
||||||
import org.apache.hc.core5.http.URIScheme;
|
|
||||||
import org.apache.hc.core5.http.config.Registry;
|
|
||||||
import org.apache.hc.core5.http.config.RegistryBuilder;
|
|
||||||
import org.apache.hc.core5.http.io.entity.EntityUtils;
|
|
||||||
import org.apache.hc.core5.testing.classic.ClassicTestServer;
|
|
||||||
import org.apache.hc.core5.util.Timeout;
|
|
||||||
import org.junit.jupiter.api.Assumptions;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unit tests for Windows negotiate authentication.
|
|
||||||
*/
|
|
||||||
public class TestWindowsNegotiateScheme {
|
|
||||||
|
|
||||||
public static final Timeout TIMEOUT = Timeout.ofMinutes(1);
|
|
||||||
|
|
||||||
@RegisterExtension
|
|
||||||
private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT);
|
|
||||||
|
|
||||||
@Test // this timeout (in ms) needs to be extended if you're actively debugging the code
|
|
||||||
@org.junit.jupiter.api.Timeout(value = 30000, unit = MILLISECONDS)
|
|
||||||
public void testNoInfiniteLoopOnSPNOutsideDomain() throws Exception {
|
|
||||||
final ClassicTestServer server = testResources.startServer(null, null, null);
|
|
||||||
server.registerHandler("/", (request, response, context) -> {
|
|
||||||
response.addHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.SPNEGO);
|
|
||||||
response.setCode(HttpStatus.SC_UNAUTHORIZED);
|
|
||||||
});
|
|
||||||
final HttpHost target = testResources.targetHost();
|
|
||||||
Assumptions.assumeTrue(WinHttpClients.isWinAuthAvailable(), "Test can only be run on Windows");
|
|
||||||
|
|
||||||
// HTTPCLIENT-1545
|
|
||||||
// If a service principal name (SPN) from outside your Windows domain tree (e.g., HTTP/example.com) is used,
|
|
||||||
// InitializeSecurityContext will return SEC_E_DOWNGRADE_DETECTED (decimal: -2146892976, hex: 0x80090350).
|
|
||||||
// Because WindowsNegotiateScheme wasn't setting the completed state correctly when authentication fails,
|
|
||||||
// HttpClient goes into an infinite loop, constantly retrying the negotiate authentication to kingdom
|
|
||||||
// come. This error message, "The system detected a possible attempt to compromise security. Please ensure that
|
|
||||||
// you can contact the server that authenticated you." is associated with SEC_E_DOWNGRADE_DETECTED.
|
|
||||||
|
|
||||||
final Registry<AuthSchemeFactory> authSchemeRegistry = RegistryBuilder.<AuthSchemeFactory>create()
|
|
||||||
.register(StandardAuthScheme.SPNEGO, context -> new WindowsNegotiateSchemeGetTokenFail(StandardAuthScheme.SPNEGO, "HTTP/example.com")).build();
|
|
||||||
|
|
||||||
final CloseableHttpClient client = testResources.startClient(builder -> builder
|
|
||||||
.setDefaultAuthSchemeRegistry(authSchemeRegistry)
|
|
||||||
);
|
|
||||||
|
|
||||||
final HttpGet httpGet = new HttpGet("/");
|
|
||||||
client.execute(target, httpGet, response -> {
|
|
||||||
EntityUtils.consume(response.getEntity());
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,107 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
====================================================================
|
|
||||||
Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
or more contributor license agreements. See the NOTICE file
|
|
||||||
distributed with this work for additional information
|
|
||||||
regarding copyright ownership. The ASF licenses this file
|
|
||||||
to you under the Apache License, Version 2.0 (the
|
|
||||||
"License"); you may not use this file except in compliance
|
|
||||||
with the License. You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing,
|
|
||||||
software distributed under the License is distributed on an
|
|
||||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
KIND, either express or implied. See the License for the
|
|
||||||
specific language governing permissions and limitations
|
|
||||||
under the License.
|
|
||||||
====================================================================
|
|
||||||
|
|
||||||
This software consists of voluntary contributions made by many
|
|
||||||
individuals on behalf of the Apache Software Foundation. For more
|
|
||||||
information on the Apache Software Foundation, please see
|
|
||||||
<http://www.apache.org />.
|
|
||||||
--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<parent>
|
|
||||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
|
||||||
<artifactId>httpclient5-parent</artifactId>
|
|
||||||
<version>5.2.2-SNAPSHOT</version>
|
|
||||||
</parent>
|
|
||||||
<artifactId>httpclient5-win</artifactId>
|
|
||||||
<name>Apache HttpClient Windows features</name>
|
|
||||||
<description>Apache HttpClient Windows specific functionality</description>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<Automatic-Module-Name>org.apache.httpcomponents.client5.httpclient5.win</Automatic-Module-Name>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
|
||||||
<artifactId>httpclient5</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
|
||||||
<artifactId>httpclient5</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
<classifier>tests</classifier>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-api</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.logging.log4j</groupId>
|
|
||||||
<artifactId>log4j-slf4j-impl</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.logging.log4j</groupId>
|
|
||||||
<artifactId>log4j-core</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.java.dev.jna</groupId>
|
|
||||||
<artifactId>jna</artifactId>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.java.dev.jna</groupId>
|
|
||||||
<artifactId>jna-platform</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.junit.jupiter</groupId>
|
|
||||||
<artifactId>junit-jupiter-migrationsupport</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.hamcrest</groupId>
|
|
||||||
<artifactId>hamcrest</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<reporting>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
|
||||||
<inherited>false</inherited>
|
|
||||||
<reportSets>
|
|
||||||
<reportSet>
|
|
||||||
<reports>
|
|
||||||
<report>index</report>
|
|
||||||
<report>dependencies</report>
|
|
||||||
<report>dependency-info</report>
|
|
||||||
<report>summary</report>
|
|
||||||
</reports>
|
|
||||||
</reportSet>
|
|
||||||
</reportSets>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</reporting>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,70 +0,0 @@
|
||||||
/*
|
|
||||||
* ====================================================================
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*
|
|
||||||
* This software consists of voluntary contributions made by many
|
|
||||||
* individuals on behalf of the Apache Software Foundation. For more
|
|
||||||
* information on the Apache Software Foundation, please see
|
|
||||||
* <http://www.apache.org/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.apache.hc.client5.http.examples.client.win;
|
|
||||||
|
|
||||||
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
|
||||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
|
||||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
|
|
||||||
import org.apache.hc.client5.http.impl.win.WinHttpClients;
|
|
||||||
import org.apache.hc.core5.http.io.entity.EntityUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This example demonstrates how to create HttpClient pre-configured
|
|
||||||
* with support for integrated Windows authentication.
|
|
||||||
*/
|
|
||||||
public class ClientWinAuth {
|
|
||||||
|
|
||||||
public final static void main(String[] args) throws Exception {
|
|
||||||
|
|
||||||
if (!WinHttpClients.isWinAuthAvailable()) {
|
|
||||||
System.out.println("Integrated Win auth is not supported!!!");
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseableHttpClient httpclient = WinHttpClients.createDefault();
|
|
||||||
// There is no need to provide user credentials
|
|
||||||
// HttpClient will attempt to access current user security context through
|
|
||||||
// Windows platform specific methods via JNI.
|
|
||||||
try {
|
|
||||||
HttpGet httpget = new HttpGet("http://winhost/");
|
|
||||||
|
|
||||||
System.out.println("Executing request " + httpget.getMethod() + " " + httpget.getUri());
|
|
||||||
CloseableHttpResponse response = httpclient.execute(httpget);
|
|
||||||
try {
|
|
||||||
System.out.println("----------------------------------------");
|
|
||||||
System.out.println(response.getCode() + " " + response.getReasonPhrase());
|
|
||||||
EntityUtils.consume(response.getEntity());
|
|
||||||
} finally {
|
|
||||||
response.close();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
httpclient.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
/*
|
|
||||||
* ====================================================================
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*
|
|
||||||
* This software consists of voluntary contributions made by many
|
|
||||||
* individuals on behalf of the Apache Software Foundation. For more
|
|
||||||
* information on the Apache Software Foundation, please see
|
|
||||||
* <http://www.apache.org/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.hc.client5.http.impl.win;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import org.apache.hc.client5.http.auth.AuthSchemeFactory;
|
|
||||||
import org.apache.hc.client5.http.auth.StandardAuthScheme;
|
|
||||||
import org.apache.hc.client5.http.impl.auth.BasicSchemeFactory;
|
|
||||||
import org.apache.hc.client5.http.impl.auth.BearerSchemeFactory;
|
|
||||||
import org.apache.hc.client5.http.impl.auth.DigestSchemeFactory;
|
|
||||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
|
||||||
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
|
|
||||||
import org.apache.hc.core5.http.config.Registry;
|
|
||||||
import org.apache.hc.core5.http.config.RegistryBuilder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory methods for {@link org.apache.hc.client5.http.impl.classic.CloseableHttpClient} instances configured to use integrated
|
|
||||||
* Windows authentication by default.
|
|
||||||
*
|
|
||||||
* @since 4.4
|
|
||||||
*/
|
|
||||||
public class WinHttpClients {
|
|
||||||
|
|
||||||
private WinHttpClients() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isWinAuthAvailable() {
|
|
||||||
String os = System.getProperty("os.name");
|
|
||||||
os = os != null ? os.toLowerCase(Locale.ROOT) : null;
|
|
||||||
return os != null && os.contains("windows");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static HttpClientBuilder createBuilder() {
|
|
||||||
if (isWinAuthAvailable()) {
|
|
||||||
final Registry<AuthSchemeFactory> authSchemeRegistry = RegistryBuilder.<AuthSchemeFactory>create()
|
|
||||||
.register(StandardAuthScheme.BASIC, BasicSchemeFactory.INSTANCE)
|
|
||||||
.register(StandardAuthScheme.DIGEST, DigestSchemeFactory.INSTANCE)
|
|
||||||
.register(StandardAuthScheme.BEARER, BearerSchemeFactory.INSTANCE)
|
|
||||||
.register(StandardAuthScheme.NTLM, WindowsNTLMSchemeFactory.DEFAULT)
|
|
||||||
.register(StandardAuthScheme.SPNEGO, WindowsNegotiateSchemeFactory.DEFAULT)
|
|
||||||
.build();
|
|
||||||
return HttpClientBuilder.create()
|
|
||||||
.setDefaultAuthSchemeRegistry(authSchemeRegistry);
|
|
||||||
}
|
|
||||||
return HttpClientBuilder.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates builder object for construction of custom
|
|
||||||
* {@link CloseableHttpClient} instances.
|
|
||||||
*/
|
|
||||||
public static HttpClientBuilder custom() {
|
|
||||||
return createBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates {@link CloseableHttpClient} instance with default
|
|
||||||
* configuration.
|
|
||||||
*/
|
|
||||||
public static CloseableHttpClient createDefault() {
|
|
||||||
return createBuilder().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates {@link CloseableHttpClient} instance with default
|
|
||||||
* configuration based on system properties.
|
|
||||||
*/
|
|
||||||
public static CloseableHttpClient createSystem() {
|
|
||||||
return createBuilder().useSystemProperties().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
/*
|
|
||||||
* ====================================================================
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*
|
|
||||||
* This software consists of voluntary contributions made by many
|
|
||||||
* individuals on behalf of the Apache Software Foundation. For more
|
|
||||||
* information on the Apache Software Foundation, please see
|
|
||||||
* <http://www.apache.org/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.apache.hc.client5.http.impl.win;
|
|
||||||
|
|
||||||
import org.apache.hc.client5.http.auth.AuthScheme;
|
|
||||||
import org.apache.hc.client5.http.auth.AuthSchemeFactory;
|
|
||||||
import org.apache.hc.client5.http.auth.StandardAuthScheme;
|
|
||||||
import org.apache.hc.core5.annotation.Contract;
|
|
||||||
import org.apache.hc.core5.annotation.Experimental;
|
|
||||||
import org.apache.hc.core5.annotation.ThreadingBehavior;
|
|
||||||
import org.apache.hc.core5.http.protocol.HttpContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link AuthSchemeFactory} implementation that creates and initializes
|
|
||||||
* {@link WindowsNegotiateScheme} using JNA to implement NTLM
|
|
||||||
*
|
|
||||||
* @since 4.4
|
|
||||||
*/
|
|
||||||
@Contract(threading = ThreadingBehavior.STATELESS)
|
|
||||||
@Experimental
|
|
||||||
public class WindowsNTLMSchemeFactory implements AuthSchemeFactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Singleton instance with a null name.
|
|
||||||
*/
|
|
||||||
public static final WindowsNTLMSchemeFactory DEFAULT = new WindowsNTLMSchemeFactory(null);
|
|
||||||
|
|
||||||
private final String servicePrincipalName;
|
|
||||||
|
|
||||||
public WindowsNTLMSchemeFactory(final String servicePrincipalName) {
|
|
||||||
super();
|
|
||||||
this.servicePrincipalName = servicePrincipalName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthScheme create(final HttpContext context) {
|
|
||||||
return new WindowsNegotiateScheme(StandardAuthScheme.NTLM, servicePrincipalName);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,294 +0,0 @@
|
||||||
/*
|
|
||||||
* ====================================================================
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*
|
|
||||||
* This software consists of voluntary contributions made by many
|
|
||||||
* individuals on behalf of the Apache Software Foundation. For more
|
|
||||||
* information on the Apache Software Foundation, please see
|
|
||||||
* <http://www.apache.org/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.hc.client5.http.impl.win;
|
|
||||||
|
|
||||||
import java.security.Principal;
|
|
||||||
|
|
||||||
import org.apache.hc.client5.http.utils.Base64;
|
|
||||||
import org.apache.hc.client5.http.RouteInfo;
|
|
||||||
import org.apache.hc.client5.http.auth.AuthChallenge;
|
|
||||||
import org.apache.hc.client5.http.auth.AuthScheme;
|
|
||||||
import org.apache.hc.client5.http.auth.AuthenticationException;
|
|
||||||
import org.apache.hc.client5.http.auth.BasicUserPrincipal;
|
|
||||||
import org.apache.hc.client5.http.auth.ChallengeType;
|
|
||||||
import org.apache.hc.client5.http.auth.CredentialsProvider;
|
|
||||||
import org.apache.hc.client5.http.auth.MalformedChallengeException;
|
|
||||||
import org.apache.hc.client5.http.auth.StandardAuthScheme;
|
|
||||||
import org.apache.hc.client5.http.protocol.HttpClientContext;
|
|
||||||
import org.apache.hc.core5.annotation.Experimental;
|
|
||||||
import org.apache.hc.core5.http.HttpHost;
|
|
||||||
import org.apache.hc.core5.http.HttpRequest;
|
|
||||||
import org.apache.hc.core5.http.protocol.HttpContext;
|
|
||||||
import org.apache.hc.core5.net.URIAuthority;
|
|
||||||
import org.apache.hc.core5.util.Args;
|
|
||||||
import org.apache.hc.core5.util.TextUtils;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.sun.jna.platform.win32.Secur32;
|
|
||||||
import com.sun.jna.platform.win32.Secur32Util;
|
|
||||||
import com.sun.jna.platform.win32.Sspi;
|
|
||||||
import com.sun.jna.platform.win32.Sspi.CredHandle;
|
|
||||||
import com.sun.jna.platform.win32.Sspi.CtxtHandle;
|
|
||||||
import com.sun.jna.platform.win32.Sspi.SecBufferDesc;
|
|
||||||
import com.sun.jna.platform.win32.Sspi.TimeStamp;
|
|
||||||
import com.sun.jna.platform.win32.SspiUtil.ManagedSecBufferDesc;
|
|
||||||
import com.sun.jna.platform.win32.Win32Exception;
|
|
||||||
import com.sun.jna.platform.win32.WinError;
|
|
||||||
import com.sun.jna.ptr.IntByReference;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Auth scheme that makes use of JNA to implement Negotiate and NTLM on Windows Platforms.
|
|
||||||
* <p>
|
|
||||||
* This will delegate negotiation to the windows machine.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @since 4.4
|
|
||||||
*/
|
|
||||||
@Experimental
|
|
||||||
public class WindowsNegotiateScheme implements AuthScheme {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(WindowsNegotiateScheme.class);
|
|
||||||
|
|
||||||
// NTLM or Negotiate
|
|
||||||
private final String schemeName;
|
|
||||||
private final String servicePrincipalName;
|
|
||||||
|
|
||||||
private ChallengeType challengeType;
|
|
||||||
private String challenge;
|
|
||||||
private CredHandle clientCred;
|
|
||||||
private CtxtHandle sspiContext;
|
|
||||||
private boolean continueNeeded;
|
|
||||||
|
|
||||||
WindowsNegotiateScheme(final String schemeName, final String servicePrincipalName) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.schemeName = (schemeName == null) ? StandardAuthScheme.SPNEGO : schemeName;
|
|
||||||
this.continueNeeded = true;
|
|
||||||
this.servicePrincipalName = servicePrincipalName;
|
|
||||||
|
|
||||||
if (LOG.isDebugEnabled()) {
|
|
||||||
LOG.debug("Created WindowsNegotiateScheme using {}", this.schemeName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dispose() {
|
|
||||||
if (clientCred != null && !clientCred.isNull()) {
|
|
||||||
final int rc = Secur32.INSTANCE.FreeCredentialsHandle(clientCred);
|
|
||||||
if (WinError.SEC_E_OK != rc) {
|
|
||||||
throw new Win32Exception(rc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sspiContext != null && !sspiContext.isNull()) {
|
|
||||||
final int rc = Secur32.INSTANCE.DeleteSecurityContext(sspiContext);
|
|
||||||
if (WinError.SEC_E_OK != rc) {
|
|
||||||
throw new Win32Exception(rc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continueNeeded = true; // waiting
|
|
||||||
clientCred = null;
|
|
||||||
sspiContext = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return schemeName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isConnectionBased() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRealm() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void processChallenge(
|
|
||||||
final AuthChallenge authChallenge,
|
|
||||||
final HttpContext context) throws MalformedChallengeException {
|
|
||||||
Args.notNull(authChallenge, "AuthChallenge");
|
|
||||||
challengeType = authChallenge.getChallengeType();
|
|
||||||
challenge = authChallenge.getValue();
|
|
||||||
if (TextUtils.isBlank(challenge)) {
|
|
||||||
if (clientCred != null) {
|
|
||||||
dispose(); // run cleanup first before throwing an exception otherwise can leak OS resources
|
|
||||||
if (continueNeeded) {
|
|
||||||
throw new IllegalStateException("Unexpected token");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isResponseReady(
|
|
||||||
final HttpHost host,
|
|
||||||
final CredentialsProvider credentialsProvider,
|
|
||||||
final HttpContext context) throws AuthenticationException {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the SAM-compatible username of the currently logged-on user.
|
|
||||||
*
|
|
||||||
* @return String.
|
|
||||||
*/
|
|
||||||
public static String getCurrentUsername() {
|
|
||||||
return Secur32Util.getUserNameEx(Secur32.EXTENDED_NAME_FORMAT.NameSamCompatible);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Principal getPrincipal() {
|
|
||||||
return new BasicUserPrincipal(getCurrentUsername());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String generateAuthResponse(
|
|
||||||
final HttpHost host,
|
|
||||||
final HttpRequest request,
|
|
||||||
final HttpContext context) throws AuthenticationException {
|
|
||||||
|
|
||||||
final HttpClientContext clientContext = HttpClientContext.adapt(context);
|
|
||||||
final String response;
|
|
||||||
if (clientCred == null) {
|
|
||||||
// client credentials handle
|
|
||||||
try {
|
|
||||||
final String username = getCurrentUsername();
|
|
||||||
final TimeStamp lifetime = new TimeStamp();
|
|
||||||
|
|
||||||
clientCred = new CredHandle();
|
|
||||||
final int rc = Secur32.INSTANCE.AcquireCredentialsHandle(username,
|
|
||||||
schemeName, Sspi.SECPKG_CRED_OUTBOUND, null, null, null, null,
|
|
||||||
clientCred, lifetime);
|
|
||||||
|
|
||||||
if (WinError.SEC_E_OK != rc) {
|
|
||||||
throw new Win32Exception(rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
final String targetName = getServicePrincipalName(request, clientContext);
|
|
||||||
response = getToken(null, null, targetName);
|
|
||||||
} catch (final RuntimeException ex) {
|
|
||||||
failAuthCleanup();
|
|
||||||
if (ex instanceof Win32Exception) {
|
|
||||||
throw new AuthenticationException("Authentication Failed", ex);
|
|
||||||
}
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
} else if (challenge == null || challenge.isEmpty()) {
|
|
||||||
failAuthCleanup();
|
|
||||||
throw new AuthenticationException("Authentication Failed");
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
final byte[] continueTokenBytes = Base64.decodeBase64(challenge);
|
|
||||||
final SecBufferDesc continueTokenBuffer = new ManagedSecBufferDesc(
|
|
||||||
Sspi.SECBUFFER_TOKEN, continueTokenBytes);
|
|
||||||
final String targetName = getServicePrincipalName(request, clientContext);
|
|
||||||
response = getToken(this.sspiContext, continueTokenBuffer, targetName);
|
|
||||||
} catch (final RuntimeException ex) {
|
|
||||||
failAuthCleanup();
|
|
||||||
if (ex instanceof Win32Exception) {
|
|
||||||
throw new AuthenticationException("Authentication Failed", ex);
|
|
||||||
}
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return schemeName + " " + response;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void failAuthCleanup() {
|
|
||||||
dispose();
|
|
||||||
this.continueNeeded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Per RFC4559, the Service Principal Name should HTTP/<hostname>. However, <hostname>
|
|
||||||
// can just be the host or the fully qualified name (e.g., see "Kerberos SPN generation"
|
|
||||||
// at http://www.chromium.org/developers/design-documents/http-authentication). Here,
|
|
||||||
// I've chosen to use the host that has been provided in HttpHost so that I don't incur
|
|
||||||
// any additional DNS lookup cost.
|
|
||||||
private String getServicePrincipalName(final HttpRequest request, final HttpClientContext clientContext) {
|
|
||||||
String spn = null;
|
|
||||||
if (this.servicePrincipalName != null) {
|
|
||||||
spn = this.servicePrincipalName;
|
|
||||||
} else if (challengeType == ChallengeType.PROXY) {
|
|
||||||
final RouteInfo route = clientContext.getHttpRoute();
|
|
||||||
if (route != null) {
|
|
||||||
spn = "HTTP/" + route.getProxyHost().getHostName();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final URIAuthority authority = request.getAuthority();
|
|
||||||
if (authority != null) {
|
|
||||||
spn = "HTTP/" + authority.getHostName();
|
|
||||||
} else {
|
|
||||||
final RouteInfo route = clientContext.getHttpRoute();
|
|
||||||
if (route != null) {
|
|
||||||
spn = "HTTP/" + route.getTargetHost().getHostName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (LOG.isDebugEnabled()) {
|
|
||||||
LOG.debug("Using SPN: {}", spn);
|
|
||||||
}
|
|
||||||
return spn;
|
|
||||||
}
|
|
||||||
|
|
||||||
// See http://msdn.microsoft.com/en-us/library/windows/desktop/aa375506(v=vs.85).aspx
|
|
||||||
String getToken(
|
|
||||||
final CtxtHandle continueCtx,
|
|
||||||
final SecBufferDesc continueToken,
|
|
||||||
final String targetName) {
|
|
||||||
final IntByReference attr = new IntByReference();
|
|
||||||
final ManagedSecBufferDesc token = new ManagedSecBufferDesc(
|
|
||||||
Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
|
|
||||||
|
|
||||||
sspiContext = new CtxtHandle();
|
|
||||||
final int rc = Secur32.INSTANCE.InitializeSecurityContext(clientCred,
|
|
||||||
continueCtx, targetName, Sspi.ISC_REQ_DELEGATE | Sspi.ISC_REQ_MUTUAL_AUTH, 0,
|
|
||||||
Sspi.SECURITY_NATIVE_DREP, continueToken, 0, sspiContext, token,
|
|
||||||
attr, null);
|
|
||||||
switch (rc) {
|
|
||||||
case WinError.SEC_I_CONTINUE_NEEDED:
|
|
||||||
continueNeeded = true;
|
|
||||||
break;
|
|
||||||
case WinError.SEC_E_OK:
|
|
||||||
dispose(); // Don't keep the context
|
|
||||||
continueNeeded = false;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dispose();
|
|
||||||
throw new Win32Exception(rc);
|
|
||||||
}
|
|
||||||
return Base64.encodeBase64String(token.getBuffer(0).getBytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isChallengeComplete() {
|
|
||||||
return !continueNeeded;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
/*
|
|
||||||
* ====================================================================
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*
|
|
||||||
* This software consists of voluntary contributions made by many
|
|
||||||
* individuals on behalf of the Apache Software Foundation. For more
|
|
||||||
* information on the Apache Software Foundation, please see
|
|
||||||
* <http://www.apache.org/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.apache.hc.client5.http.impl.win;
|
|
||||||
|
|
||||||
import org.apache.hc.client5.http.auth.AuthScheme;
|
|
||||||
import org.apache.hc.client5.http.auth.AuthSchemeFactory;
|
|
||||||
import org.apache.hc.client5.http.auth.StandardAuthScheme;
|
|
||||||
import org.apache.hc.core5.annotation.Contract;
|
|
||||||
import org.apache.hc.core5.annotation.Experimental;
|
|
||||||
import org.apache.hc.core5.annotation.ThreadingBehavior;
|
|
||||||
import org.apache.hc.core5.http.protocol.HttpContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link AuthSchemeFactory} implementation that creates and initializes
|
|
||||||
* {@link WindowsNegotiateScheme} using JNA to Negotiate credentials
|
|
||||||
*
|
|
||||||
* @since 4.4
|
|
||||||
*/
|
|
||||||
@Contract(threading = ThreadingBehavior.STATELESS)
|
|
||||||
@Experimental
|
|
||||||
public class WindowsNegotiateSchemeFactory implements AuthSchemeFactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Singleton instance with a null name.
|
|
||||||
*/
|
|
||||||
public static final WindowsNegotiateSchemeFactory DEFAULT = new WindowsNegotiateSchemeFactory(null);
|
|
||||||
|
|
||||||
private final String servicePrincipalName;
|
|
||||||
|
|
||||||
public WindowsNegotiateSchemeFactory(final String servicePrincipalName) {
|
|
||||||
super();
|
|
||||||
this.servicePrincipalName = servicePrincipalName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthScheme create(final HttpContext context) {
|
|
||||||
return new WindowsNegotiateScheme(StandardAuthScheme.SPNEGO, servicePrincipalName);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* ====================================================================
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*
|
|
||||||
* This software consists of voluntary contributions made by many
|
|
||||||
* individuals on behalf of the Apache Software Foundation. For more
|
|
||||||
* information on the Apache Software Foundation, please see
|
|
||||||
* <http://www.apache.org/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Auth scheme that makes use of JNA to implement Negotiate and NTLM on Windows Platforms.
|
|
||||||
* <p>
|
|
||||||
* Please note this class is considered experimental and may be discontinued or removed
|
|
||||||
* in the future.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
package org.apache.hc.client5.http.impl.win;
|
|
|
@ -1,29 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
contributor license agreements. See the NOTICE file distributed with
|
|
||||||
this work for additional information regarding copyright ownership.
|
|
||||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
(the "License"); you may not use this file except in compliance with
|
|
||||||
the License. You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
-->
|
|
||||||
<Configuration status="WARN" name="XMLConfigTest">
|
|
||||||
<Appenders>
|
|
||||||
<Console name="STDOUT">
|
|
||||||
<PatternLayout pattern="%d %-5level [%t][%logger]%notEmpty{[%markerSimpleName]} %msg%n%xThrowable" />
|
|
||||||
</Console>
|
|
||||||
</Appenders>
|
|
||||||
<Loggers>
|
|
||||||
<Root level="WARN">
|
|
||||||
<AppenderRef ref="STDOUT" />
|
|
||||||
</Root>
|
|
||||||
</Loggers>
|
|
||||||
</Configuration>
|
|
|
@ -43,7 +43,14 @@ import org.apache.hc.core5.util.LangUtils;
|
||||||
* Windows specific attributes such as name of the domain the user belongs to.
|
* Windows specific attributes such as name of the domain the user belongs to.
|
||||||
*
|
*
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
|
*
|
||||||
|
* @deprecated Do not use. the NTLM authentication scheme is no longer supported.
|
||||||
|
* Consider using Basic or Bearer authentication with TLS instead.
|
||||||
|
*
|
||||||
|
* @see UsernamePasswordCredentials
|
||||||
|
* @see BearerToken
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
@Contract(threading = ThreadingBehavior.IMMUTABLE)
|
@Contract(threading = ThreadingBehavior.IMMUTABLE)
|
||||||
public class NTCredentials implements Credentials, Serializable {
|
public class NTCredentials implements Credentials, Serializable {
|
||||||
|
|
||||||
|
@ -69,9 +76,7 @@ public class NTCredentials implements Credentials, Serializable {
|
||||||
* @param workstation The workstation the authentication request is originating from.
|
* @param workstation The workstation the authentication request is originating from.
|
||||||
* Essentially, the computer name for this machine.
|
* Essentially, the computer name for this machine.
|
||||||
* @param domain The domain to authenticate within.
|
* @param domain The domain to authenticate within.
|
||||||
* @deprecated (5.3) Use {@link #NTCredentials(char[], String, String, String)}
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public NTCredentials(
|
public NTCredentials(
|
||||||
final String userName,
|
final String userName,
|
||||||
final char[] password,
|
final char[] password,
|
||||||
|
@ -89,9 +94,7 @@ public class NTCredentials implements Credentials, Serializable {
|
||||||
* Essentially, the computer name for this machine.
|
* Essentially, the computer name for this machine.
|
||||||
* @param domain The domain to authenticate within.
|
* @param domain The domain to authenticate within.
|
||||||
* @param netbiosDomain The netbios version of the domain name.
|
* @param netbiosDomain The netbios version of the domain name.
|
||||||
@deprecated (5.3) Use {@link #NTCredentials(char[], String, String, String)}
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public NTCredentials(
|
public NTCredentials(
|
||||||
final String userName,
|
final String userName,
|
||||||
final char[] password,
|
final char[] password,
|
||||||
|
@ -114,7 +117,6 @@ public class NTCredentials implements Credentials, Serializable {
|
||||||
* This constructor creates a new instance of NTCredentials, determining the workstation name at runtime
|
* This constructor creates a new instance of NTCredentials, determining the workstation name at runtime
|
||||||
* using the {@link #getWorkstationName()} method. The workstation name will be converted to uppercase
|
* using the {@link #getWorkstationName()} method. The workstation name will be converted to uppercase
|
||||||
* using the {@link java.util.Locale#ROOT} locale.
|
* using the {@link java.util.Locale#ROOT} locale.
|
||||||
* @since 5.3
|
|
||||||
*/
|
*/
|
||||||
public NTCredentials(
|
public NTCredentials(
|
||||||
final char[] password,
|
final char[] password,
|
||||||
|
|
|
@ -57,7 +57,11 @@ public final class StandardAuthScheme {
|
||||||
/**
|
/**
|
||||||
* The NTLM authentication scheme is a proprietary Microsoft Windows
|
* The NTLM authentication scheme is a proprietary Microsoft Windows
|
||||||
* authentication protocol as defined in [MS-NLMP].
|
* authentication protocol as defined in [MS-NLMP].
|
||||||
|
*
|
||||||
|
* @deprecated Do not use. the NTLM authentication scheme is no longer supported.
|
||||||
|
* Consider using Basic or Bearer authentication with TLS instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static final String NTLM = "NTLM";
|
public static final String NTLM = "NTLM";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -67,7 +67,6 @@ public class DefaultAuthenticationStrategy implements AuthenticationStrategy {
|
||||||
Collections.unmodifiableList(Arrays.asList(
|
Collections.unmodifiableList(Arrays.asList(
|
||||||
StandardAuthScheme.SPNEGO,
|
StandardAuthScheme.SPNEGO,
|
||||||
StandardAuthScheme.KERBEROS,
|
StandardAuthScheme.KERBEROS,
|
||||||
StandardAuthScheme.NTLM,
|
|
||||||
StandardAuthScheme.BEARER,
|
StandardAuthScheme.BEARER,
|
||||||
StandardAuthScheme.DIGEST,
|
StandardAuthScheme.DIGEST,
|
||||||
StandardAuthScheme.BASIC));
|
StandardAuthScheme.BASIC));
|
||||||
|
|
|
@ -61,7 +61,6 @@ import org.apache.hc.client5.http.impl.auth.BasicSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.BearerSchemeFactory;
|
import org.apache.hc.client5.http.impl.auth.BearerSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.DigestSchemeFactory;
|
import org.apache.hc.client5.http.impl.auth.DigestSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.KerberosSchemeFactory;
|
import org.apache.hc.client5.http.impl.auth.KerberosSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.NTLMSchemeFactory;
|
|
||||||
import org.apache.hc.client5.http.impl.auth.SPNegoSchemeFactory;
|
import org.apache.hc.client5.http.impl.auth.SPNegoSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.SystemDefaultCredentialsProvider;
|
import org.apache.hc.client5.http.impl.auth.SystemDefaultCredentialsProvider;
|
||||||
import org.apache.hc.client5.http.impl.nio.MultihomeConnectionInitiator;
|
import org.apache.hc.client5.http.impl.nio.MultihomeConnectionInitiator;
|
||||||
|
@ -822,7 +821,6 @@ public class H2AsyncClientBuilder {
|
||||||
.register(StandardAuthScheme.BASIC, BasicSchemeFactory.INSTANCE)
|
.register(StandardAuthScheme.BASIC, BasicSchemeFactory.INSTANCE)
|
||||||
.register(StandardAuthScheme.DIGEST, DigestSchemeFactory.INSTANCE)
|
.register(StandardAuthScheme.DIGEST, DigestSchemeFactory.INSTANCE)
|
||||||
.register(StandardAuthScheme.BEARER, BearerSchemeFactory.INSTANCE)
|
.register(StandardAuthScheme.BEARER, BearerSchemeFactory.INSTANCE)
|
||||||
.register(StandardAuthScheme.NTLM, NTLMSchemeFactory.INSTANCE)
|
|
||||||
.register(StandardAuthScheme.SPNEGO, SPNegoSchemeFactory.DEFAULT)
|
.register(StandardAuthScheme.SPNEGO, SPNegoSchemeFactory.DEFAULT)
|
||||||
.register(StandardAuthScheme.KERBEROS, KerberosSchemeFactory.DEFAULT)
|
.register(StandardAuthScheme.KERBEROS, KerberosSchemeFactory.DEFAULT)
|
||||||
.build();
|
.build();
|
||||||
|
|
|
@ -67,7 +67,6 @@ import org.apache.hc.client5.http.impl.auth.BasicSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.BearerSchemeFactory;
|
import org.apache.hc.client5.http.impl.auth.BearerSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.DigestSchemeFactory;
|
import org.apache.hc.client5.http.impl.auth.DigestSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.KerberosSchemeFactory;
|
import org.apache.hc.client5.http.impl.auth.KerberosSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.NTLMSchemeFactory;
|
|
||||||
import org.apache.hc.client5.http.impl.auth.SPNegoSchemeFactory;
|
import org.apache.hc.client5.http.impl.auth.SPNegoSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.SystemDefaultCredentialsProvider;
|
import org.apache.hc.client5.http.impl.auth.SystemDefaultCredentialsProvider;
|
||||||
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
|
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
|
||||||
|
@ -1009,7 +1008,6 @@ public class HttpAsyncClientBuilder {
|
||||||
.register(StandardAuthScheme.BASIC, BasicSchemeFactory.INSTANCE)
|
.register(StandardAuthScheme.BASIC, BasicSchemeFactory.INSTANCE)
|
||||||
.register(StandardAuthScheme.DIGEST, DigestSchemeFactory.INSTANCE)
|
.register(StandardAuthScheme.DIGEST, DigestSchemeFactory.INSTANCE)
|
||||||
.register(StandardAuthScheme.BEARER, BearerSchemeFactory.INSTANCE)
|
.register(StandardAuthScheme.BEARER, BearerSchemeFactory.INSTANCE)
|
||||||
.register(StandardAuthScheme.NTLM, NTLMSchemeFactory.INSTANCE)
|
|
||||||
.register(StandardAuthScheme.SPNEGO, SPNegoSchemeFactory.DEFAULT)
|
.register(StandardAuthScheme.SPNEGO, SPNegoSchemeFactory.DEFAULT)
|
||||||
.register(StandardAuthScheme.KERBEROS, KerberosSchemeFactory.DEFAULT)
|
.register(StandardAuthScheme.KERBEROS, KerberosSchemeFactory.DEFAULT)
|
||||||
.build();
|
.build();
|
||||||
|
|
|
@ -32,7 +32,10 @@ package org.apache.hc.client5.http.impl.auth;
|
||||||
* Type2 challenge.
|
* Type2 challenge.
|
||||||
*
|
*
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
|
*
|
||||||
|
* @deprecated Do not use. the NTLM authentication scheme is no longer supported
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public interface NTLMEngine {
|
public interface NTLMEngine {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -32,7 +32,10 @@ import org.apache.hc.client5.http.auth.AuthenticationException;
|
||||||
* Signals NTLM protocol failure.
|
* Signals NTLM protocol failure.
|
||||||
*
|
*
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
|
*
|
||||||
|
* @deprecated Do not use.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class NTLMEngineException extends AuthenticationException {
|
public class NTLMEngineException extends AuthenticationException {
|
||||||
|
|
||||||
private static final long serialVersionUID = 6027981323731768824L;
|
private static final long serialVersionUID = 6027981323731768824L;
|
||||||
|
|
|
@ -48,7 +48,10 @@ import org.apache.hc.client5.http.utils.ByteArrayBuilder;
|
||||||
* authentication protocol.
|
* authentication protocol.
|
||||||
*
|
*
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
|
*
|
||||||
|
* @deprecated Do not use.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
final class NTLMEngineImpl implements NTLMEngine {
|
final class NTLMEngineImpl implements NTLMEngine {
|
||||||
|
|
||||||
/** Unicode encoding */
|
/** Unicode encoding */
|
||||||
|
|
|
@ -30,13 +30,12 @@ import java.security.Principal;
|
||||||
|
|
||||||
import org.apache.hc.client5.http.auth.AuthChallenge;
|
import org.apache.hc.client5.http.auth.AuthChallenge;
|
||||||
import org.apache.hc.client5.http.auth.AuthScheme;
|
import org.apache.hc.client5.http.auth.AuthScheme;
|
||||||
import org.apache.hc.client5.http.auth.StandardAuthScheme;
|
|
||||||
import org.apache.hc.client5.http.auth.AuthScope;
|
import org.apache.hc.client5.http.auth.AuthScope;
|
||||||
import org.apache.hc.client5.http.auth.AuthenticationException;
|
import org.apache.hc.client5.http.auth.AuthenticationException;
|
||||||
import org.apache.hc.client5.http.auth.Credentials;
|
import org.apache.hc.client5.http.auth.Credentials;
|
||||||
import org.apache.hc.client5.http.auth.CredentialsProvider;
|
import org.apache.hc.client5.http.auth.CredentialsProvider;
|
||||||
import org.apache.hc.client5.http.auth.MalformedChallengeException;
|
import org.apache.hc.client5.http.auth.MalformedChallengeException;
|
||||||
import org.apache.hc.client5.http.auth.NTCredentials;
|
import org.apache.hc.client5.http.auth.StandardAuthScheme;
|
||||||
import org.apache.hc.client5.http.protocol.HttpClientContext;
|
import org.apache.hc.client5.http.protocol.HttpClientContext;
|
||||||
import org.apache.hc.core5.http.HttpHost;
|
import org.apache.hc.core5.http.HttpHost;
|
||||||
import org.apache.hc.core5.http.HttpRequest;
|
import org.apache.hc.core5.http.HttpRequest;
|
||||||
|
@ -50,7 +49,14 @@ import org.slf4j.LoggerFactory;
|
||||||
* and optimized for Windows platforms.
|
* and optimized for Windows platforms.
|
||||||
*
|
*
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
|
*
|
||||||
|
* @deprecated Do not use. the NTLM authentication scheme is no longer supported.
|
||||||
|
* Consider using Basic or Bearer authentication with TLS instead.
|
||||||
|
*
|
||||||
|
* @see BasicScheme
|
||||||
|
* @see BearerScheme
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public final class NTLMScheme implements AuthScheme {
|
public final class NTLMScheme implements AuthScheme {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(NTLMScheme.class);
|
private static final Logger LOG = LoggerFactory.getLogger(NTLMScheme.class);
|
||||||
|
@ -68,7 +74,7 @@ public final class NTLMScheme implements AuthScheme {
|
||||||
|
|
||||||
private State state;
|
private State state;
|
||||||
private String challenge;
|
private String challenge;
|
||||||
private NTCredentials credentials;
|
private org.apache.hc.client5.http.auth.NTCredentials credentials;
|
||||||
|
|
||||||
public NTLMScheme(final NTLMEngine engine) {
|
public NTLMScheme(final NTLMEngine engine) {
|
||||||
super();
|
super();
|
||||||
|
@ -134,8 +140,8 @@ public final class NTLMScheme implements AuthScheme {
|
||||||
final AuthScope authScope = new AuthScope(host, null, getName());
|
final AuthScope authScope = new AuthScope(host, null, getName());
|
||||||
final Credentials credentials = credentialsProvider.getCredentials(
|
final Credentials credentials = credentialsProvider.getCredentials(
|
||||||
authScope, context);
|
authScope, context);
|
||||||
if (credentials instanceof NTCredentials) {
|
if (credentials instanceof org.apache.hc.client5.http.auth.NTCredentials) {
|
||||||
this.credentials = (NTCredentials) credentials;
|
this.credentials = (org.apache.hc.client5.http.auth.NTCredentials) credentials;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,13 @@ import org.apache.hc.core5.http.protocol.HttpContext;
|
||||||
* implementation.
|
* implementation.
|
||||||
*
|
*
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
|
* @deprecated Do not use. the NTLM authentication scheme is no longer supported.
|
||||||
|
* Consider using Basic or Bearer authentication with TLS instead.
|
||||||
|
*
|
||||||
|
* @see BasicSchemeFactory
|
||||||
|
* @see BearerSchemeFactory
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
@Contract(threading = ThreadingBehavior.STATELESS)
|
@Contract(threading = ThreadingBehavior.STATELESS)
|
||||||
public class NTLMSchemeFactory implements AuthSchemeFactory {
|
public class NTLMSchemeFactory implements AuthSchemeFactory {
|
||||||
|
|
||||||
|
|
|
@ -36,9 +36,8 @@ import java.net.URL;
|
||||||
import org.apache.hc.client5.http.auth.AuthScope;
|
import org.apache.hc.client5.http.auth.AuthScope;
|
||||||
import org.apache.hc.client5.http.auth.Credentials;
|
import org.apache.hc.client5.http.auth.Credentials;
|
||||||
import org.apache.hc.client5.http.auth.CredentialsStore;
|
import org.apache.hc.client5.http.auth.CredentialsStore;
|
||||||
import org.apache.hc.client5.http.auth.NTCredentials;
|
|
||||||
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
|
|
||||||
import org.apache.hc.client5.http.auth.StandardAuthScheme;
|
import org.apache.hc.client5.http.auth.StandardAuthScheme;
|
||||||
|
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
|
||||||
import org.apache.hc.client5.http.protocol.HttpClientContext;
|
import org.apache.hc.client5.http.protocol.HttpClientContext;
|
||||||
import org.apache.hc.core5.annotation.Contract;
|
import org.apache.hc.core5.annotation.Contract;
|
||||||
import org.apache.hc.core5.annotation.ThreadingBehavior;
|
import org.apache.hc.core5.annotation.ThreadingBehavior;
|
||||||
|
@ -54,6 +53,7 @@ import org.apache.hc.core5.util.Args;
|
||||||
* @since 4.3
|
* @since 4.3
|
||||||
*/
|
*/
|
||||||
@Contract(threading = ThreadingBehavior.SAFE)
|
@Contract(threading = ThreadingBehavior.SAFE)
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class SystemDefaultCredentialsProvider implements CredentialsStore {
|
public class SystemDefaultCredentialsProvider implements CredentialsStore {
|
||||||
|
|
||||||
private final BasicCredentialsProvider internal;
|
private final BasicCredentialsProvider internal;
|
||||||
|
@ -126,11 +126,12 @@ public class SystemDefaultCredentialsProvider implements CredentialsStore {
|
||||||
if (systemcreds != null) {
|
if (systemcreds != null) {
|
||||||
final String domain = System.getProperty("http.auth.ntlm.domain");
|
final String domain = System.getProperty("http.auth.ntlm.domain");
|
||||||
if (domain != null) {
|
if (domain != null) {
|
||||||
return new NTCredentials(systemcreds.getUserName(), systemcreds.getPassword(), null, domain);
|
return new org.apache.hc.client5.http.auth.NTCredentials(
|
||||||
|
systemcreds.getUserName(), systemcreds.getPassword(), null, domain);
|
||||||
}
|
}
|
||||||
if (StandardAuthScheme.NTLM.equalsIgnoreCase(authScope.getSchemeName())) {
|
if (StandardAuthScheme.NTLM.equalsIgnoreCase(authScope.getSchemeName())) {
|
||||||
// Domain may be specified in a fully qualified user name
|
// Domain may be specified in a fully qualified user name
|
||||||
return new NTCredentials(
|
return new org.apache.hc.client5.http.auth.NTCredentials(
|
||||||
systemcreds.getUserName(), systemcreds.getPassword(), null, null);
|
systemcreds.getUserName(), systemcreds.getPassword(), null, null);
|
||||||
}
|
}
|
||||||
return new UsernamePasswordCredentials(systemcreds.getUserName(), systemcreds.getPassword());
|
return new UsernamePasswordCredentials(systemcreds.getUserName(), systemcreds.getPassword());
|
||||||
|
|
|
@ -70,7 +70,6 @@ import org.apache.hc.client5.http.impl.auth.BasicSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.BearerSchemeFactory;
|
import org.apache.hc.client5.http.impl.auth.BearerSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.DigestSchemeFactory;
|
import org.apache.hc.client5.http.impl.auth.DigestSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.KerberosSchemeFactory;
|
import org.apache.hc.client5.http.impl.auth.KerberosSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.NTLMSchemeFactory;
|
|
||||||
import org.apache.hc.client5.http.impl.auth.SPNegoSchemeFactory;
|
import org.apache.hc.client5.http.impl.auth.SPNegoSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.SystemDefaultCredentialsProvider;
|
import org.apache.hc.client5.http.impl.auth.SystemDefaultCredentialsProvider;
|
||||||
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
|
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
|
||||||
|
@ -966,7 +965,6 @@ public class HttpClientBuilder {
|
||||||
.register(StandardAuthScheme.BASIC, BasicSchemeFactory.INSTANCE)
|
.register(StandardAuthScheme.BASIC, BasicSchemeFactory.INSTANCE)
|
||||||
.register(StandardAuthScheme.DIGEST, DigestSchemeFactory.INSTANCE)
|
.register(StandardAuthScheme.DIGEST, DigestSchemeFactory.INSTANCE)
|
||||||
.register(StandardAuthScheme.BEARER, BearerSchemeFactory.INSTANCE)
|
.register(StandardAuthScheme.BEARER, BearerSchemeFactory.INSTANCE)
|
||||||
.register(StandardAuthScheme.NTLM, NTLMSchemeFactory.INSTANCE)
|
|
||||||
.register(StandardAuthScheme.SPNEGO, SPNegoSchemeFactory.DEFAULT)
|
.register(StandardAuthScheme.SPNEGO, SPNegoSchemeFactory.DEFAULT)
|
||||||
.register(StandardAuthScheme.KERBEROS, KerberosSchemeFactory.DEFAULT)
|
.register(StandardAuthScheme.KERBEROS, KerberosSchemeFactory.DEFAULT)
|
||||||
.build();
|
.build();
|
||||||
|
|
|
@ -49,7 +49,6 @@ import org.apache.hc.client5.http.impl.auth.BasicSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.DigestSchemeFactory;
|
import org.apache.hc.client5.http.impl.auth.DigestSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.HttpAuthenticator;
|
import org.apache.hc.client5.http.impl.auth.HttpAuthenticator;
|
||||||
import org.apache.hc.client5.http.impl.auth.KerberosSchemeFactory;
|
import org.apache.hc.client5.http.impl.auth.KerberosSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.auth.NTLMSchemeFactory;
|
|
||||||
import org.apache.hc.client5.http.impl.auth.SPNegoSchemeFactory;
|
import org.apache.hc.client5.http.impl.auth.SPNegoSchemeFactory;
|
||||||
import org.apache.hc.client5.http.impl.io.ManagedHttpClientConnectionFactory;
|
import org.apache.hc.client5.http.impl.io.ManagedHttpClientConnectionFactory;
|
||||||
import org.apache.hc.client5.http.io.ManagedHttpClientConnection;
|
import org.apache.hc.client5.http.io.ManagedHttpClientConnection;
|
||||||
|
@ -121,7 +120,6 @@ public class ProxyClient {
|
||||||
this.authSchemeRegistry = RegistryBuilder.<AuthSchemeFactory>create()
|
this.authSchemeRegistry = RegistryBuilder.<AuthSchemeFactory>create()
|
||||||
.register(StandardAuthScheme.BASIC, BasicSchemeFactory.INSTANCE)
|
.register(StandardAuthScheme.BASIC, BasicSchemeFactory.INSTANCE)
|
||||||
.register(StandardAuthScheme.DIGEST, DigestSchemeFactory.INSTANCE)
|
.register(StandardAuthScheme.DIGEST, DigestSchemeFactory.INSTANCE)
|
||||||
.register(StandardAuthScheme.NTLM, NTLMSchemeFactory.INSTANCE)
|
|
||||||
.register(StandardAuthScheme.SPNEGO, SPNegoSchemeFactory.DEFAULT)
|
.register(StandardAuthScheme.SPNEGO, SPNegoSchemeFactory.DEFAULT)
|
||||||
.register(StandardAuthScheme.KERBEROS, KerberosSchemeFactory.DEFAULT)
|
.register(StandardAuthScheme.KERBEROS, KerberosSchemeFactory.DEFAULT)
|
||||||
.build();
|
.build();
|
||||||
|
|
|
@ -35,6 +35,7 @@ import java.io.ObjectOutputStream;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class TestCredentials {
|
public class TestCredentials {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -70,7 +70,7 @@ public class TestRequestConfig {
|
||||||
.setCircularRedirectsAllowed(true)
|
.setCircularRedirectsAllowed(true)
|
||||||
.setMaxRedirects(100)
|
.setMaxRedirects(100)
|
||||||
.setCookieSpec(StandardCookieSpec.STRICT)
|
.setCookieSpec(StandardCookieSpec.STRICT)
|
||||||
.setTargetPreferredAuthSchemes(Collections.singletonList(StandardAuthScheme.NTLM))
|
.setTargetPreferredAuthSchemes(Collections.singletonList(StandardAuthScheme.BEARER))
|
||||||
.setProxyPreferredAuthSchemes(Collections.singletonList(StandardAuthScheme.DIGEST))
|
.setProxyPreferredAuthSchemes(Collections.singletonList(StandardAuthScheme.DIGEST))
|
||||||
.setContentCompressionEnabled(false)
|
.setContentCompressionEnabled(false)
|
||||||
.build();
|
.build();
|
||||||
|
@ -82,7 +82,7 @@ public class TestRequestConfig {
|
||||||
Assertions.assertTrue(config.isCircularRedirectsAllowed());
|
Assertions.assertTrue(config.isCircularRedirectsAllowed());
|
||||||
Assertions.assertEquals(100, config.getMaxRedirects());
|
Assertions.assertEquals(100, config.getMaxRedirects());
|
||||||
Assertions.assertEquals(StandardCookieSpec.STRICT, config.getCookieSpec());
|
Assertions.assertEquals(StandardCookieSpec.STRICT, config.getCookieSpec());
|
||||||
Assertions.assertEquals(Collections.singletonList(StandardAuthScheme.NTLM), config.getTargetPreferredAuthSchemes());
|
Assertions.assertEquals(Collections.singletonList(StandardAuthScheme.BEARER), config.getTargetPreferredAuthSchemes());
|
||||||
Assertions.assertEquals(Collections.singletonList(StandardAuthScheme.DIGEST), config.getProxyPreferredAuthSchemes());
|
Assertions.assertEquals(Collections.singletonList(StandardAuthScheme.DIGEST), config.getProxyPreferredAuthSchemes());
|
||||||
Assertions.assertFalse(config.isContentCompressionEnabled());
|
Assertions.assertFalse(config.isContentCompressionEnabled());
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,7 +208,7 @@ public class ClientConfiguration {
|
||||||
final RequestConfig defaultRequestConfig = RequestConfig.custom()
|
final RequestConfig defaultRequestConfig = RequestConfig.custom()
|
||||||
.setCookieSpec(StandardCookieSpec.STRICT)
|
.setCookieSpec(StandardCookieSpec.STRICT)
|
||||||
.setExpectContinueEnabled(true)
|
.setExpectContinueEnabled(true)
|
||||||
.setTargetPreferredAuthSchemes(Arrays.asList(StandardAuthScheme.NTLM, StandardAuthScheme.DIGEST))
|
.setTargetPreferredAuthSchemes(Arrays.asList(StandardAuthScheme.DIGEST))
|
||||||
.setProxyPreferredAuthSchemes(Collections.singletonList(StandardAuthScheme.BASIC))
|
.setProxyPreferredAuthSchemes(Collections.singletonList(StandardAuthScheme.BASIC))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
|
@ -315,19 +315,6 @@ public class TestAuthChallengeParser {
|
||||||
assertThat(params1.get(1), NameValuePairMatcher.equals("blah", null));
|
assertThat(params1.get(1), NameValuePairMatcher.equals("blah", null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParseEmptyNTLMAuthChallenge() throws Exception {
|
|
||||||
final CharArrayBuffer buffer = new CharArrayBuffer(64);
|
|
||||||
buffer.append(StandardAuthScheme.NTLM);
|
|
||||||
final ParserCursor cursor = new ParserCursor(0, buffer.length());
|
|
||||||
final List<AuthChallenge> challenges = parser.parse(ChallengeType.TARGET, buffer, cursor);
|
|
||||||
Assertions.assertNotNull(challenges);
|
|
||||||
Assertions.assertEquals(1, challenges.size());
|
|
||||||
final AuthChallenge challenge1 = challenges.get(0);
|
|
||||||
Assertions.assertEquals(StandardAuthScheme.NTLM, challenge1.getSchemeName());
|
|
||||||
Assertions.assertNull(challenge1.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseParameterAndToken68AuthChallengeMix() throws Exception {
|
public void testParseParameterAndToken68AuthChallengeMix() throws Exception {
|
||||||
final CharArrayBuffer buffer = new CharArrayBuffer(64);
|
final CharArrayBuffer buffer = new CharArrayBuffer(64);
|
||||||
|
|
|
@ -66,12 +66,4 @@ public class TestBasicAuthCache {
|
||||||
Assertions.assertNull(cache.get(new HttpHost("localhost", 80)));
|
Assertions.assertNull(cache.get(new HttpHost("localhost", 80)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStoreNonSerializable() throws Exception {
|
|
||||||
final BasicAuthCache cache = new BasicAuthCache();
|
|
||||||
final AuthScheme authScheme = new NTLMScheme();
|
|
||||||
cache.put(new HttpHost("localhost", 80), authScheme);
|
|
||||||
Assertions.assertNull(cache.get(new HttpHost("localhost", 80)));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ public class TestHttpAuthenticator {
|
||||||
this.authSchemeRegistry = RegistryBuilder.<AuthSchemeFactory>create()
|
this.authSchemeRegistry = RegistryBuilder.<AuthSchemeFactory>create()
|
||||||
.register(StandardAuthScheme.BASIC, BasicSchemeFactory.INSTANCE)
|
.register(StandardAuthScheme.BASIC, BasicSchemeFactory.INSTANCE)
|
||||||
.register(StandardAuthScheme.DIGEST, DigestSchemeFactory.INSTANCE)
|
.register(StandardAuthScheme.DIGEST, DigestSchemeFactory.INSTANCE)
|
||||||
.register(StandardAuthScheme.NTLM, NTLMSchemeFactory.INSTANCE).build();
|
.build();
|
||||||
this.context.setAttribute(HttpClientContext.AUTHSCHEME_REGISTRY, this.authSchemeRegistry);
|
this.context.setAttribute(HttpClientContext.AUTHSCHEME_REGISTRY, this.authSchemeRegistry);
|
||||||
this.httpAuthenticator = new HttpAuthenticator();
|
this.httpAuthenticator = new HttpAuthenticator();
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import java.util.Random;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class TestNTLMEngineImpl {
|
public class TestNTLMEngineImpl {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.junit.jupiter.api.Test;
|
||||||
/**
|
/**
|
||||||
* Unit tests for {@link NTLMScheme}.
|
* Unit tests for {@link NTLMScheme}.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class TestNTLMScheme {
|
public class TestNTLMScheme {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -45,7 +45,6 @@ import org.apache.hc.client5.http.classic.methods.HttpPost;
|
||||||
import org.apache.hc.client5.http.entity.EntityBuilder;
|
import org.apache.hc.client5.http.entity.EntityBuilder;
|
||||||
import org.apache.hc.client5.http.impl.auth.BasicScheme;
|
import org.apache.hc.client5.http.impl.auth.BasicScheme;
|
||||||
import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
|
import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
|
||||||
import org.apache.hc.client5.http.impl.auth.NTLMScheme;
|
|
||||||
import org.apache.hc.client5.http.protocol.HttpClientContext;
|
import org.apache.hc.client5.http.protocol.HttpClientContext;
|
||||||
import org.apache.hc.core5.http.ClassicHttpRequest;
|
import org.apache.hc.core5.http.ClassicHttpRequest;
|
||||||
import org.apache.hc.core5.http.ClassicHttpResponse;
|
import org.apache.hc.core5.http.ClassicHttpResponse;
|
||||||
|
@ -209,7 +208,14 @@ public class TestProtocolExec {
|
||||||
|
|
||||||
final AuthExchange authExchange = new AuthExchange();
|
final AuthExchange authExchange = new AuthExchange();
|
||||||
authExchange.setState(AuthExchange.State.SUCCESS);
|
authExchange.setState(AuthExchange.State.SUCCESS);
|
||||||
authExchange.select(new NTLMScheme());
|
authExchange.select(new BasicScheme() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isConnectionBased() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
context.setAuthExchange(target, authExchange);
|
context.setAuthExchange(target, authExchange);
|
||||||
|
|
||||||
context.setCredentialsProvider(CredentialsProviderBuilder.create()
|
context.setCredentialsProvider(CredentialsProviderBuilder.create()
|
||||||
|
|
|
@ -44,7 +44,6 @@ import org.apache.hc.client5.http.config.RequestConfig;
|
||||||
import org.apache.hc.client5.http.entity.EntityBuilder;
|
import org.apache.hc.client5.http.entity.EntityBuilder;
|
||||||
import org.apache.hc.client5.http.impl.DefaultRedirectStrategy;
|
import org.apache.hc.client5.http.impl.DefaultRedirectStrategy;
|
||||||
import org.apache.hc.client5.http.impl.auth.BasicScheme;
|
import org.apache.hc.client5.http.impl.auth.BasicScheme;
|
||||||
import org.apache.hc.client5.http.impl.auth.NTLMScheme;
|
|
||||||
import org.apache.hc.client5.http.protocol.HttpClientContext;
|
import org.apache.hc.client5.http.protocol.HttpClientContext;
|
||||||
import org.apache.hc.client5.http.protocol.RedirectLocations;
|
import org.apache.hc.client5.http.protocol.RedirectLocations;
|
||||||
import org.apache.hc.client5.http.protocol.RedirectStrategy;
|
import org.apache.hc.client5.http.protocol.RedirectStrategy;
|
||||||
|
@ -187,7 +186,14 @@ public class TestRedirectExec {
|
||||||
targetAuthExchange.select(new BasicScheme());
|
targetAuthExchange.select(new BasicScheme());
|
||||||
final AuthExchange proxyAuthExchange = new AuthExchange();
|
final AuthExchange proxyAuthExchange = new AuthExchange();
|
||||||
proxyAuthExchange.setState(AuthExchange.State.SUCCESS);
|
proxyAuthExchange.setState(AuthExchange.State.SUCCESS);
|
||||||
proxyAuthExchange.select(new NTLMScheme());
|
proxyAuthExchange.select(new BasicScheme() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isConnectionBased() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
context.setAuthExchange(target, targetAuthExchange);
|
context.setAuthExchange(target, targetAuthExchange);
|
||||||
context.setAuthExchange(proxy, proxyAuthExchange);
|
context.setAuthExchange(proxy, proxyAuthExchange);
|
||||||
|
|
||||||
|
|
6
pom.xml
6
pom.xml
|
@ -123,11 +123,6 @@
|
||||||
<artifactId>httpclient5-fluent</artifactId>
|
<artifactId>httpclient5-fluent</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
|
||||||
<artifactId>httpclient5-win</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
@ -205,7 +200,6 @@
|
||||||
<module>httpclient5</module>
|
<module>httpclient5</module>
|
||||||
<module>httpclient5-fluent</module>
|
<module>httpclient5-fluent</module>
|
||||||
<module>httpclient5-cache</module>
|
<module>httpclient5-cache</module>
|
||||||
<module>httpclient5-win</module>
|
|
||||||
<module>httpclient5-testing</module>
|
<module>httpclient5-testing</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue