You need to access a resource that is protected by Microsoft's NTLM authentication protocol.
Create an instance of NTCredentials
with a username, password, host,
and domain, and call setCredentials()
on the HttpState
associated with an instance of HttpClient
. The following example demonstrates
the use of NTCredentials
to access a
resource on host test.windowsmachine.com
, which is on the
domain TESTDOM
:
import org.apache.commons.httpclient.Credentials; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpState; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.NTCredentials; import org.apache.commons.httpclient.methods.GetMethod; HttpClient client = new HttpClient( ); // Set credentials on the client Credentials credentials = new NTCredentials( "testuser", "crazypass", "homecomputer ", "TESTDOM" ); HttpState state = client.getState( ); state( ).setCredentials( null, null, credentials ); String url = "http://webmail.domain.biz/exchange/"; HttpMethod method = new GetMethod( url ); client.executeMethod( method ); String response = method.getResponseBodyAsString( ); System.out.println( response ); method.releaseConnection( );
The parameters to the constructor of NTCredentials
are the username, the password,
a hostname, and a domain. The hostname is the name of the machine making
the request, and, in this case, the third parameter is homecomputer
. When this Credential
object is set in the HttpState
object, the first two parameters
specify the authentication realm and the host to apply a Credential
object to. The previous example
sets both the authentication realm and the host to null
; this makes the NTCredentials
object the default Credentials
to use if there is no realm or
host specified. If we were using one instance of HttpClient
to connect to two different hosts
with two different NTCredentials
objects, both Credentials
objects
could be added to HttpState
with the
following code:
HttpClient client = new HttpClient( ); Credentials credentials1 = new NTCredentials( "testuser", "crazypass", "homecomputer", "TESTDOM" ); Credentials credentials2 = new NTCredentials( "anotheruser", "password2", "homecomputer", "DIFFERENT_DOMAIN" ); HttpState state = client.getState( ); state( ).setCredentials( null, "webmail.domain.biz", credentials1 ); state( ).setCredentials( null, "silly-iis-server.lame.net", credentials2 ); // Execute a request which uses credentials1 String url = "http://webmail.domain.biz/exchange/"; HttpMethod method = new GetMethod( url ); client.executeMethod( method ); // Execute a request which uses credentials2 String url2 = "http://silly-iis-server.lame.net/test/"; HttpMethod method2 = new GetMethod( url2 ); client.executeMethod( method2 );
The host webmail.domain.biz
tries to authenticate the first request against the TESTDOM
domain, and the silly-iis-server.lame.net
host tries to
authenticate the second request against the DIFFERENT_DOMAIN
domain. Since the HttpState
is configured with two separate
Credentials
objects for different
hosts, both requests are successfully authenticated.
No one will dispute the assertion that the HTTP protocol has dramatically changed the world we live in, and one of the reasons for this success is the openness of the protocol. Unfortunately, NTLM is proprietary and undocumented, and this is reason enough to avoid using it entirely. If you are stuck with NTLM and you want to learn more about the protocol, it is described in excruciating detail at http://www.innovation.ch/java/ntlm.html and http://davenport.sourceforge.net/ntlm.html.