diff --git a/httpclient/src/main/java/org/apache/http/auth/AuthScope.java b/httpclient/src/main/java/org/apache/http/auth/AuthScope.java index 548854009c..ebbfecb25a 100644 --- a/httpclient/src/main/java/org/apache/http/auth/AuthScope.java +++ b/httpclient/src/main/java/org/apache/http/auth/AuthScope.java @@ -66,6 +66,11 @@ public class AuthScope { */ public static final String ANY_SCHEME = null; + /** + * The {@code null} value represents any target host. + */ + public static final String ANY_TARGET_HOST_URL = null; + /** * Default scope matching any host, port, realm and authentication scheme. * In the future versions of HttpClient the use of this parameter will be @@ -88,6 +93,9 @@ public class AuthScope { /** The original host, if known */ private final HttpHost origin; + /** The target host, as advertised to the user */ + private final String targetHostUrl; + /** * Defines auth scope with the given {@code host}, {@code port}, {@code realm}, and * {@code schemeName}. @@ -100,17 +108,30 @@ public class AuthScope { * to any realm on the host. * @param schemeName authentication scheme. May be {@link #ANY_SCHEME} if applies * to any scheme supported by the host. + * @param targetHostUrl target host advertised to the user. May be {@link #ANY_TARGET_HOST_URL}. + * + * @since 4.5.3 */ public AuthScope( final String host, final int port, final String realm, - final String schemeName) { + final String schemeName, + final String targetHostUrl) { this.host = host == null ? ANY_HOST: host.toLowerCase(Locale.ROOT); this.port = port < 0 ? ANY_PORT : port; this.realm = realm == null ? ANY_REALM : realm; this.scheme = schemeName == null ? ANY_SCHEME : schemeName.toUpperCase(Locale.ROOT); this.origin = null; + this.targetHostUrl = targetHostUrl; + } + + /** + * Defines auth scope with the given {@code host}, {@code port}, {@code realm}, and + * {@code schemeName}. + */ + public AuthScope(final String host, final int port, final String realm, final String schemeName) { + this(host, port, realm, schemeName, ANY_TARGET_HOST_URL); } /** @@ -121,19 +142,33 @@ public AuthScope( * to any realm on the host. * @param schemeName authentication scheme. May be {@link #ANY_SCHEME} if applies * to any scheme supported by the host. + * @param targetHostUrl target host advertised to the user. May be {@link #ANY_TARGET_HOST_URL}. * - * @since 4.2 + * @since 4.5.3 */ public AuthScope( final HttpHost origin, final String realm, - final String schemeName) { + final String schemeName, + final String targetHostUrl) { Args.notNull(origin, "Host"); this.host = origin.getHostName().toLowerCase(Locale.ROOT); this.port = origin.getPort() < 0 ? ANY_PORT : origin.getPort(); this.realm = realm == null ? ANY_REALM : realm; this.scheme = schemeName == null ? ANY_SCHEME : schemeName.toUpperCase(Locale.ROOT); this.origin = origin; + this.targetHostUrl = targetHostUrl; + } + + /** + * Defines auth scope for a specific host of origin. + * + * @param origin host of origin + * + * @since 4.2 + */ + public AuthScope(final HttpHost origin, final String realm, final String schemeName) { + this(origin, realm, schemeName, ANY_TARGET_HOST_URL); } /** @@ -184,6 +219,7 @@ public AuthScope(final AuthScope authscope) { this.realm = authscope.getRealm(); this.scheme = authscope.getScheme(); this.origin = authscope.getOrigin(); + this.targetHostUrl = authscope.getTargetHostUrl(); } /** @@ -223,6 +259,13 @@ public String getScheme() { return this.scheme; } + /** + * @return the target host + */ + public String getTargetHostUrl() { + return targetHostUrl; + } + /** * Tests if the authentication scopes match. * diff --git a/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java b/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java index cd15aeabb9..84085ad9a8 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/AuthenticationStrategyImpl.java @@ -59,6 +59,7 @@ import org.apache.http.config.Lookup; import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; +import org.apache.http.protocol.HttpCoreContext; import org.apache.http.util.Args; import org.apache.http.util.CharArrayBuffer; @@ -188,11 +189,20 @@ public Queue select( final AuthScheme authScheme = authSchemeProvider.create(context); authScheme.processChallenge(challenge); + final String targetHostUrl; + if (context != null) { + final HttpHost httpTargetHost = ((HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST)); + targetHostUrl = httpTargetHost != null ? httpTargetHost.toURI() : null; + } else { + targetHostUrl = null; + } + final AuthScope authScope = new AuthScope( authhost.getHostName(), authhost.getPort(), authScheme.getRealm(), - authScheme.getSchemeName()); + authScheme.getSchemeName(), + targetHostUrl); final Credentials credentials = credsProvider.getCredentials(authScope); if (credentials != null) { diff --git a/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java b/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java index debe142fa7..7da1a8564a 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/SystemDefaultCredentialsProvider.java @@ -27,7 +27,9 @@ package org.apache.http.impl.client; import java.net.Authenticator; +import java.net.MalformedURLException; import java.net.PasswordAuthentication; +import java.net.URL; import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -93,14 +95,21 @@ private static PasswordAuthentication getSystemCreds( final HttpHost origin = authscope.getOrigin(); final String protocol = origin != null ? origin.getSchemeName() : (port == 443 ? "https" : "http"); + final URL targetHostUrl; + try { + targetHostUrl= authscope.getTargetHostUrl() != null ? new URL(authscope.getTargetHostUrl()) : null; + } catch (final MalformedURLException ex) { + // should never happen + throw new IllegalStateException("Malformed target host", ex); + } return Authenticator.requestPasswordAuthentication( hostname, null, port, protocol, - null, + authscope.getRealm(), translateScheme(authscope.getScheme()), - null, + targetHostUrl, requestorType); } @@ -131,7 +140,7 @@ public Credentials getCredentials(final AuthScope authscope) { systemcreds = new PasswordAuthentication(proxyUser, proxyPassword != null ? proxyPassword.toCharArray() : new char[] {}); } } - } catch (NumberFormatException ex) { + } catch (final NumberFormatException ex) { } } } diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/SystemDefaultRoutePlanner.java b/httpclient/src/main/java/org/apache/http/impl/conn/SystemDefaultRoutePlanner.java index 6b872b9eb4..43b1e02bbd 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/SystemDefaultRoutePlanner.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/SystemDefaultRoutePlanner.java @@ -86,22 +86,12 @@ protected HttpHost determineProxy( } final InetSocketAddress isa = (InetSocketAddress) p.address(); // assume default scheme (http) - result = new HttpHost(getHost(isa), isa.getPort()); + result = new HttpHost(isa.getAddress(), isa.getHostString(), isa.getPort(), null); } return result; } - private String getHost(final InetSocketAddress isa) { - - //@@@ Will this work with literal IPv6 addresses, or do we - //@@@ need to wrap these in [] for the string representation? - //@@@ Having it in this method at least allows for easy workarounds. - return isa.isUnresolved() ? - isa.getHostName() : isa.getAddress().getHostAddress(); - - } - private Proxy chooseProxy(final List proxies) { Proxy result = null; // check the list for one we can use