* Added HTTP parameters to define the order of preference for supported auth schemes for target host and proxy authentication
* Added SPNEGO auth policy git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@818601 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
9cbf76568f
commit
af4b944189
|
@ -1,6 +1,10 @@
|
|||
Changes since 4.0
|
||||
-------------------
|
||||
|
||||
* Added parameters to define the order of preference for supported auth
|
||||
schemes for target host and proxy authentication.
|
||||
Contributed by Oleg Kalnichevski <olegk at apache.org>
|
||||
|
||||
* [HTTPCLIENT-875] DefaultClientConnectionOperator#openConnection doesn't
|
||||
update the connection state if the connection socket changed after
|
||||
the call to SocketFactory#connectSocket().
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
package org.apache.http.auth.params;
|
||||
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
|
||||
/**
|
||||
* Parameter names for HTTP authentication classes.
|
||||
*
|
||||
|
@ -42,4 +44,26 @@ public interface AuthPNames {
|
|||
*/
|
||||
public static final String CREDENTIAL_CHARSET = "http.auth.credential-charset";
|
||||
|
||||
/**
|
||||
* Defines the order of preference for supported {@link AuthScheme}s when
|
||||
* authenticating with the target host.
|
||||
* <p>
|
||||
* This parameter expects a value of type {@link java.util.Collection}. The
|
||||
* collection is expected to contain {@link String} instances representing
|
||||
* a name of an authentication scheme as returned by
|
||||
* {@link AuthScheme#getSchemeName()}.
|
||||
*/
|
||||
public static final String TARGET_AUTH_PREF = "http.auth.target-scheme-pref";
|
||||
|
||||
/**
|
||||
* Defines the order of preference for supported {@link AuthScheme}s when
|
||||
* authenticating with the proxy host.
|
||||
* <p>
|
||||
* This parameter expects a value of type {@link java.util.Collection}. The
|
||||
* collection is expected to contain {@link String} instances representing
|
||||
* a name of an authentication scheme as returned by
|
||||
* {@link AuthScheme#getSchemeName()}.
|
||||
*/
|
||||
public static final String PROXY_AUTH_PREF = "http.auth.proxy-scheme-pref";
|
||||
|
||||
}
|
||||
|
|
|
@ -59,4 +59,11 @@ public final class AuthPolicy {
|
|||
*/
|
||||
public static final String BASIC = "Basic";
|
||||
|
||||
/**
|
||||
* SPNEGO/Kerberos Authentication scheme.
|
||||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
public static final String SPNEGO = "negotiate";
|
||||
|
||||
}
|
||||
|
|
|
@ -89,8 +89,9 @@ public interface ClientContext {
|
|||
public static final String PROXY_AUTH_STATE = "http.auth.proxy-scope";
|
||||
|
||||
/**
|
||||
* RESERVED. DO NOT USE!!!
|
||||
* @deprecated do not use
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String AUTH_SCHEME_PREF = "http.auth.scheme-pref";
|
||||
|
||||
/**
|
||||
|
|
|
@ -35,18 +35,18 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.annotation.Immutable;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.http.FormattedHeader;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.annotation.Immutable;
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.AuthSchemeRegistry;
|
||||
import org.apache.http.auth.AuthenticationException;
|
||||
import org.apache.http.auth.MalformedChallengeException;
|
||||
import org.apache.http.client.AuthenticationHandler;
|
||||
import org.apache.http.client.params.AuthPolicy;
|
||||
import org.apache.http.client.protocol.ClientContext;
|
||||
import org.apache.http.protocol.HTTP;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
|
@ -64,9 +64,10 @@ public abstract class AbstractAuthenticationHandler implements AuthenticationHan
|
|||
|
||||
private static final List<String> DEFAULT_SCHEME_PRIORITY =
|
||||
Collections.unmodifiableList(Arrays.asList(new String[] {
|
||||
"ntlm",
|
||||
"digest",
|
||||
"basic"
|
||||
AuthPolicy.SPNEGO,
|
||||
AuthPolicy.NTLM,
|
||||
AuthPolicy.DIGEST,
|
||||
AuthPolicy.BASIC
|
||||
}));
|
||||
|
||||
public AbstractAuthenticationHandler() {
|
||||
|
@ -106,11 +107,31 @@ public abstract class AbstractAuthenticationHandler implements AuthenticationHan
|
|||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns default list of auth scheme names in their order of preference.
|
||||
*
|
||||
* @return list of auth scheme names
|
||||
*/
|
||||
protected List<String> getAuthPreferences() {
|
||||
return DEFAULT_SCHEME_PRIORITY;
|
||||
}
|
||||
|
||||
public AuthScheme selectScheme(
|
||||
/**
|
||||
* Returns default list of auth scheme names in their order of preference
|
||||
* based on the HTTP response and the current execution context.
|
||||
*
|
||||
* @param response HTTP response.
|
||||
* @param context HTTP execution context.
|
||||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
protected List<String> getAuthPreferences(
|
||||
final HttpResponse response,
|
||||
final HttpContext context) {
|
||||
return getAuthPreferences();
|
||||
}
|
||||
|
||||
public AuthScheme selectScheme(
|
||||
final Map<String, Header> challenges,
|
||||
final HttpResponse response,
|
||||
final HttpContext context) throws AuthenticationException {
|
||||
|
@ -121,11 +142,9 @@ public abstract class AbstractAuthenticationHandler implements AuthenticationHan
|
|||
throw new IllegalStateException("AuthScheme registry not set in HTTP context");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<String> authPrefs = (Collection<String>) context.getAttribute(
|
||||
ClientContext.AUTH_SCHEME_PREF);
|
||||
Collection<String> authPrefs = getAuthPreferences(response, context);
|
||||
if (authPrefs == null) {
|
||||
authPrefs = getAuthPreferences();
|
||||
authPrefs = DEFAULT_SCHEME_PRIORITY;
|
||||
}
|
||||
|
||||
if (this.log.isDebugEnabled()) {
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
package org.apache.http.impl.client;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.annotation.Immutable;
|
||||
|
@ -36,6 +37,7 @@ import org.apache.http.HttpResponse;
|
|||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.auth.AUTH;
|
||||
import org.apache.http.auth.MalformedChallengeException;
|
||||
import org.apache.http.auth.params.AuthPNames;
|
||||
import org.apache.http.client.AuthenticationHandler;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
|
||||
|
@ -72,4 +74,18 @@ public class DefaultProxyAuthenticationHandler extends AbstractAuthenticationHan
|
|||
return parseChallenges(headers);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getAuthPreferences(
|
||||
final HttpResponse response,
|
||||
final HttpContext context) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> authpref = (List<String>) response.getParams().getParameter(
|
||||
AuthPNames.PROXY_AUTH_PREF);
|
||||
if (authpref != null) {
|
||||
return authpref;
|
||||
} else {
|
||||
return super.getAuthPreferences(response, context);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
package org.apache.http.impl.client;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.annotation.Immutable;
|
||||
|
@ -36,6 +37,7 @@ import org.apache.http.HttpResponse;
|
|||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.auth.AUTH;
|
||||
import org.apache.http.auth.MalformedChallengeException;
|
||||
import org.apache.http.auth.params.AuthPNames;
|
||||
import org.apache.http.client.AuthenticationHandler;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
|
||||
|
@ -72,4 +74,19 @@ public class DefaultTargetAuthenticationHandler extends AbstractAuthenticationHa
|
|||
return parseChallenges(headers);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getAuthPreferences(
|
||||
final HttpResponse response,
|
||||
final HttpContext context) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> authpref = (List<String>) response.getParams().getParameter(
|
||||
AuthPNames.TARGET_AUTH_PREF);
|
||||
if (authpref != null) {
|
||||
return authpref;
|
||||
} else {
|
||||
return super.getAuthPreferences(response, context);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -103,8 +103,8 @@ pwd
|
|||
those applications that do not want the overhead of full transport security
|
||||
through TLS/SSL encryption.</para>
|
||||
</formalpara>
|
||||
<listitem>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title>NTLM:</title>
|
||||
<para>NTLM is a proprietary authentication scheme developed by Microsoft and
|
||||
|
@ -130,8 +130,8 @@ pwd
|
|||
If this parameter is not set HttpClient will handle authentication
|
||||
automatically.</para>
|
||||
</formalpara>
|
||||
<listitem>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title>'http.auth.credential-charset':</title>
|
||||
<para>defines the charset to be used when encoding user credentials. This
|
||||
|
@ -139,7 +139,41 @@ pwd
|
|||
this parameter is not set <literal>US-ASCII</literal> will be used.</para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title>'http.auth.target-scheme-pref':</title>
|
||||
<para>Defines the order of preference for supported
|
||||
<interfacename>AuthScheme</interfacename>s when authenticating with the
|
||||
target host. This parameter expects a value of type
|
||||
<interface>java.util.Collection</interface>. The collection is expected
|
||||
to contain <classname>java.lang.String</classname> instances representing a
|
||||
name of an authentication scheme as returned by
|
||||
<methodname>AuthScheme#getSchemeName()</methodname></para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<formalpara>
|
||||
<title>'http.auth.proxy-scheme-pref':</title>
|
||||
<para>Defines the order of preference for supported
|
||||
<interfacename>AuthScheme</interfacename>s when authenticating with the
|
||||
proxy host. This parameter expects a value of type
|
||||
<interface>java.util.Collection</interface>. The collection is expected
|
||||
to contain <classname>java.lang.String</classname> instances representing a
|
||||
name of an authentication scheme as returned by
|
||||
<methodname>AuthScheme#getSchemeName()</methodname></para>
|
||||
</formalpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>For example, one can force HttpClient to use a different order of preference for
|
||||
authentication schemes</para>
|
||||
<programlisting><![CDATA[
|
||||
DefaultHttpClient httpclient = new DefaultHttpClient(ccm, params);
|
||||
// Choose BASIC over DIGEST for proxy authentication
|
||||
List<String> authpref = new ArrayList<String>();
|
||||
authpref.add(AuthPolicy.BASIC);
|
||||
authpref.add(AuthPolicy.DIGEST);
|
||||
httpclient.getParams().setParameter(AuthPNames.PROXY_AUTH_PREF, authpref);
|
||||
]]></programlisting>
|
||||
</section>
|
||||
<section>
|
||||
<title>Authentication scheme registry</title>
|
||||
|
@ -332,44 +366,59 @@ httpclient.addRequestInterceptor(preemptiveAuth, 0);
|
|||
|
||||
<section>
|
||||
<title><literal>SPNEGO</literal>/Kerberos Authentication</title>
|
||||
<para><literal>SPNEGO</literal> (<emphasis>S</emphasis>imple and <emphasis>P</emphasis>rotected <literal>GSSAPI</literal>
|
||||
<emphasis>Nego</emphasis>tiation Mechanism) is designed to allow for authentication
|
||||
to services when neither end knows what the other can use/provide. It is most
|
||||
commonly used to do Kerberos authentication. It can wrap other mechanisms, however
|
||||
the current version in HTTPClient is designed solely with Kerberos in mind. The image below shows a simple authentication process.
|
||||
</para>
|
||||
<para><literal>SPNEGO</literal> (<emphasis>S</emphasis>imple and
|
||||
<emphasis>P</emphasis>rotected <literal>GSSAPI</literal>
|
||||
<emphasis>Nego</emphasis>tiation Mechanism) is designed to allow for authentication to
|
||||
services when neither end knows what the other can use/provide. It is most commonly used
|
||||
to do Kerberos authentication. It can wrap other mechanisms, however the current version
|
||||
in HTTPClient is designed solely with Kerberos in mind. The image below shows a simple
|
||||
authentication process. </para>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref=".//images/SPNEGO_cropped.png" />
|
||||
<imagedata fileref=".//images/SPNEGO_cropped.png"/>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
<sidebar>
|
||||
<para>1. Client Web Browser does HTTP GET for resource.</para>
|
||||
<para>2. Web server returns HTTP 401 status and a header: "WWW-Authenticate: Negotiate</para>
|
||||
<para>3. Client generates a NegTokenInit, base64 encodes it, and resubmits the GET with an Authorization header: "Authorization: Negotiate <base64 encoding>".</para>
|
||||
<para>4. Server decodes the NegTokenInit, extracts the supported MechTypes (only Kerberos V5 in our case), ensures it is one of the expected ones, and then extracts the MechToken (Kerberos Token) and authenticates it.</para>
|
||||
<para>4a. If more processing is required another HTTP 401 is returned to the client with more data in the the WWW-Authenticate header. Client takes the info and generates another token passing this back in the Authorization header.... until complete.</para>
|
||||
<para>5. When the client has been authenticated the Web server should return the HTTP 200 status, a final WWW-Authenticate header and the page content.</para>
|
||||
<sidebar>
|
||||
<para>1. Client Web Browser does HTTP GET for resource.</para>
|
||||
<para>2. Web server returns HTTP 401 status and a header: "WWW-Authenticate:
|
||||
Negotiate</para>
|
||||
<para>3. Client generates a NegTokenInit, base64 encodes it, and resubmits the GET with
|
||||
an Authorization header: "Authorization: Negotiate <base64
|
||||
encoding>".</para>
|
||||
<para>4. Server decodes the NegTokenInit, extracts the supported MechTypes (only
|
||||
Kerberos V5 in our case), ensures it is one of the expected ones, and then extracts
|
||||
the MechToken (Kerberos Token) and authenticates it.</para>
|
||||
<para>4a. If more processing is required another HTTP 401 is returned to the client with
|
||||
more data in the the WWW-Authenticate header. Client takes the info and generates
|
||||
another token passing this back in the Authorization header.... until
|
||||
complete.</para>
|
||||
<para>5. When the client has been authenticated the Web server should return the HTTP
|
||||
200 status, a final WWW-Authenticate header and the page content.</para>
|
||||
</sidebar>
|
||||
<section>
|
||||
<title>HTTPClient Implementation</title>
|
||||
|
||||
<para>Supports Sun Java versions 1.5 and up.</para>
|
||||
<para>The JRE provides the supporting classes to do nearly all the kerberos and SPNEGO token handling. This means that a lot of the setup
|
||||
is for the GSS classes. The NegotiateScheme is a simple class to handle marshalling the tokens and reading and writing the correct headers.</para>
|
||||
<para>The JRE provides the supporting classes to do nearly all the kerberos and SPNEGO
|
||||
token handling. This means that a lot of the setup is for the GSS classes. The
|
||||
NegotiateScheme is a simple class to handle marshalling the tokens and reading and
|
||||
writing the correct headers.</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Usage.</title>
|
||||
|
||||
<para>The best way to start is to grab the KerberosHttpClient.java file in examples and try and get it to work.
|
||||
There are a lot of issues that can happen but if lucky it'll work without too much problem. It should also
|
||||
provide some output to debug with.</para>
|
||||
<para>The best way to start is to grab the KerberosHttpClient.java file in examples and
|
||||
try and get it to work. There are a lot of issues that can happen but if lucky it'll
|
||||
work without too much problem. It should also provide some output to debug
|
||||
with.</para>
|
||||
|
||||
<para>In windows it should default to using the logged in credentials, this
|
||||
can be overridden by using 'kinit' e.g. <literal>$JAVA_HOME\bin\kinit testuser@AD.EXAMPLE.NET</literal>, which is very
|
||||
helpful for testing and debugging issues. Remove the cache file created to revert back to the windows
|
||||
Kerberos cache.</para>
|
||||
<para>Make sure to list domain_realms in the krb5.conf file. This is a major source of problems.</para>
|
||||
<para>In windows it should default to using the logged in credentials, this can be
|
||||
overridden by using 'kinit' e.g. <literal>$JAVA_HOME\bin\kinit
|
||||
testuser@AD.EXAMPLE.NET</literal>, which is very helpful for testing and
|
||||
debugging issues. Remove the cache file created to revert back to the windows
|
||||
Kerberos cache.</para>
|
||||
<para>Make sure to list domain_realms in the krb5.conf file. This is a major source of
|
||||
problems.</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>NegotiateSchemeFactory Class</title>
|
||||
|
@ -379,35 +428,44 @@ Kerberos cache.</para>
|
|||
<section>
|
||||
<title>setStripPort(boolean)</title>
|
||||
|
||||
<para>Strips the port off service names e.g. HTTP/webserver.ad.example.net:8080 -> HTTP/webserver.ad.example.net</para>
|
||||
<para>Strips the port off service names e.g. HTTP/webserver.ad.example.net:8080 ->
|
||||
HTTP/webserver.ad.example.net</para>
|
||||
|
||||
<para>Found it useful when using JbossNegotiation.</para>
|
||||
</section>
|
||||
<section>
|
||||
<title> setSpnegoCreate(boolean)</title>
|
||||
|
||||
<para>If using Java 1.5 or a Kerberos ticket an attempt will be made to wrap it up into a SPNEGO token. Again for JbossNegotiation. II7 accepts plain Kerberos tickets.</para>
|
||||
<para>If using Java 1.5 or a Kerberos ticket an attempt will be made to wrap it up into
|
||||
a SPNEGO token. Again for JbossNegotiation. II7 accepts plain Kerberos
|
||||
tickets.</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>setSpengoGenerator(SpnegoTokenGenerator)</title>
|
||||
|
||||
<para>Inject a custom SpnegoTokenGenerator class to do the Kerberos to SPNEGO token wrapping. BouncySpnegoTokenGenerator example
|
||||
is provided. This requires the BouncyCastle libs <ulink url="http://www.bouncycastle.org/java.html">"http://www.bouncycastle.org/java.html"</ulink>
|
||||
</para>
|
||||
<para>Inject a custom SpnegoTokenGenerator class to do the Kerberos to SPNEGO token
|
||||
wrapping. BouncySpnegoTokenGenerator example is provided. This requires the
|
||||
BouncyCastle libs <ulink url="http://www.bouncycastle.org/java.html"
|
||||
>"http://www.bouncycastle.org/java.html"</ulink>
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>GSS/Java Kerberos Setup.</title>
|
||||
|
||||
<para>This documentation assumes you are using windows but much of the informationapplies to Unix as well.</para>
|
||||
<para>The org.ietf.jgss classes have lots of possible configuration parameters,
|
||||
mainly in the krb5.conf/krb5.ini file. Some more info on the format at
|
||||
<ulink url="http://web.mit.edu/kerberos/krb5-1.4/krb5-1.4.1/doc/krb5-admin/krb5.conf.html">http://web.mit.edu/kerberos/krb5-1.4/krb5-1.4.1/doc/krb5-admin/krb5.conf.html</ulink>.</para>
|
||||
<para>This documentation assumes you are using windows but much of the
|
||||
informationapplies to Unix as well.</para>
|
||||
<para>The org.ietf.jgss classes have lots of possible configuration parameters, mainly
|
||||
in the krb5.conf/krb5.ini file. Some more info on the format at <ulink
|
||||
url="http://web.mit.edu/kerberos/krb5-1.4/krb5-1.4.1/doc/krb5-admin/krb5.conf.html"
|
||||
>http://web.mit.edu/kerberos/krb5-1.4/krb5-1.4.1/doc/krb5-admin/krb5.conf.html</ulink>.</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>login.conf file</title>
|
||||
|
||||
<para>The following configuration is a basic setup that works in Windows XP against both IIS7 and JbossNegotiate modules.</para>
|
||||
<para>The system property that can be use to point to the login.conf file is <emphasis>java.security.auth.login.config</emphasis>.</para>
|
||||
<para>The following configuration is a basic setup that works in Windows XP against both
|
||||
IIS7 and JbossNegotiate modules.</para>
|
||||
<para>The system property that can be use to point to the login.conf file is
|
||||
<emphasis>java.security.auth.login.config</emphasis>.</para>
|
||||
<para>Sample usage...</para>
|
||||
<programlisting>System.setProperty("java.security.auth.login.config", "login.conf");</programlisting>
|
||||
|
||||
|
@ -432,7 +490,7 @@ com.sun.security.jgss.accept {
|
|||
<para>If unspecified the system default will be used. Override with...</para>
|
||||
<programlisting>System.setProperty("java.security.krb5.conf", "krb5.conf");</programlisting>
|
||||
<para>Example file contents...</para>
|
||||
|
||||
|
||||
<programlisting><![CDATA[
|
||||
[libdefaults]
|
||||
default_realm = AD.EXAMPLE.NET
|
||||
|
|
Loading…
Reference in New Issue