net.sourceforge.spnego
Class SpnegoHttpURLConnection

java.lang.Object
  extended by net.sourceforge.spnego.SpnegoHttpURLConnection

public final class SpnegoHttpURLConnection
extends Object

This Class may be used by custom clients as a convenience when connecting to a protected HTTP server.

This mechanism is an alternative to HTTP Basic Authentication where the HTTP server does not support Basic Auth but instead has SPNEGO support (take a look at SpnegoHttpFilter).

A krb5.conf and a login.conf is required when using this class. Take a look at the spnego.sourceforge.net documentation for an example krb5.conf and login.conf file. Also, you must provide a keytab file, or a username and password, or allowtgtsessionkey.

Example usage (username/password):

     public static void main(final String[] args) throws Exception {
         System.setProperty("java.security.krb5.conf", "krb5.conf");
         System.setProperty("sun.security.krb5.debug", "true");
         System.setProperty("java.security.auth.login.config", "login.conf");
         
         SpnegoHttpURLConnection spnego = null;
         
         try {
             spnego = new SpnegoHttpURLConnection("spnego-client", "dfelix", "myp@s5");
             spnego.connect(new URL("http://medusa:8080/index.jsp"));
             
             System.out.println(spnego.getResponseCode());
         
         } finally {
             if (null != spnego) {
                 spnego.disconnect();
             }
         }
     }
 

Alternatively, if the server supports HTTP Basic Authentication, this Class is NOT needed and instead you can do something like the following:

     public static void main(final String[] args) throws Exception {
         final String creds = "dfelix:myp@s5";
         
         final String token = Base64.encode(creds.getBytes());
         
         URL url = new URL("http://medusa:8080/index.jsp");
         
         HttpURLConnection conn = (HttpURLConnection) url.openConnection();
         
         conn.setRequestProperty(Constants.AUTHZ_HEADER
                 , Constants.BASIC_HEADER + " " + token);
                 
         conn.connect();
         
         System.out.println("Response Code:" + conn.getResponseCode());
     }
 

To see a working example and instructions on how to use a keytab, take a look at the creating a client keytab example.

Finally, the SpnegoSOAPConnection class is another example of a class that uses this class.

Author:
Darwin V. Felix

Field Summary
private  boolean autoDisposeCreds
          Determines if the GSSCredentials (if any) used during the connection request should be automatically disposed by this class when finished.
private  boolean cntxtEstablished
          Flag to determine if GSSContext has been established.
private  HttpURLConnection conn
          Ref to HTTP URL Connection object after calling connect method.
private  boolean connected
          If false, this connection object has not created a communications link to the specified URL.
private  GSSCredential credential
          Client's credentials.
private static byte[] EMPTY_BYTE
           
private static Lock LOCK
          GSSContext is not thread-safe.
private static Logger LOGGER
           
private  LoginContext loginContext
          Login Context for authenticating client.
private  boolean reqCredDeleg
          Request credential to be delegated.
private  String requestMethod
          Default is GET.
private  Map<String,List<String>> requestProperties
           
 
Constructor Summary
SpnegoHttpURLConnection(GSSCredential creds)
          Create an instance where the GSSCredential is specified by the parameter and where the GSSCredential is automatically disposed after use.
SpnegoHttpURLConnection(GSSCredential creds, boolean dispose)
          Create an instance where the GSSCredential is specified by the parameter and whether the GSSCredential should be disposed after use.
SpnegoHttpURLConnection(String loginModuleName)
          Creates an instance where the LoginContext relies on a keytab file being specified by "java.security.auth.login.config" or where LoginContext relies on tgtsessionkey.
SpnegoHttpURLConnection(String loginModuleName, String username, String password)
          Creates an instance where the LoginContext does not require a keytab file.
 
Method Summary
 void addRequestProperty(String key, String value)
          Adds an HTTP Request property.
private  void assertConnected()
          Throws IllegalStateException if this connection object has not yet created a communications link to the specified URL.
private  void assertKeyValue(String key, String value)
          Internal sanity check to validate not null key/value pairs.
private  void assertNotConnected()
          Throws IllegalStateException if this connection object has already created a communications link to the specified URL.
 HttpURLConnection connect(URL url)
          Opens a communications link to the resource referenced by this URL, if such a connection has not already been established.
 HttpURLConnection connect(URL url, ByteArrayOutputStream dooutput)
          Opens a communications link to the resource referenced by this URL, if such a connection has not already been established.
 void disconnect()
          Logout and clear request properties.
private  void dispose(GSSContext context)
          Logout the LoginContext instance, and call dispose() on GSSCredential if autoDisposeCreds is set to true, and call dispose on the passed-in GSSContext instance.
 InputStream getErrorStream()
          Returns an error stream that reads from this open connection.
private  GSSContext getGSSContext(URL url)
          Returns a GSSContextt for the given url with a default lifetime.
 String getHeaderField(int index)
          Get header value at specified index.
 String getHeaderField(String name)
          Get header value by header name.
 String getHeaderFieldKey(int index)
          Get header field key at specified index.
 InputStream getInputStream()
          Returns an input stream that reads from this open connection.
 OutputStream getOutputStream()
          Returns an output stream that writes to this open connection.
 int getResponseCode()
          Returns HTTP Status code.
 String getResponseMessage()
          Returns HTTP Status message.
 boolean isContextEstablished()
          Returns true if GSSContext has been established.
 void requestCredDeleg(boolean requestDelegation)
          Request that this GSSCredential be allowed for delegation.
 void setRequestMethod(String method)
          May override the default GET method.
 void setRequestProperty(String key, String value)
          Sets an HTTP Request property.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

LOGGER

private static final Logger LOGGER

LOCK

private static final Lock LOCK
GSSContext is not thread-safe.


EMPTY_BYTE

private static final byte[] EMPTY_BYTE

connected

private transient boolean connected
If false, this connection object has not created a communications link to the specified URL. If true, the communications link has been established.


requestMethod

private transient String requestMethod
Default is GET.

See Also:
HttpURLConnection.getRequestMethod()

requestProperties

private final transient Map<String,List<String>> requestProperties
See Also:
URLConnection.getRequestProperties()

loginContext

private final transient LoginContext loginContext
Login Context for authenticating client. If username/password or GSSCredential is provided (in constructor) then this field will always be null.


credential

private transient GSSCredential credential
Client's credentials. If username/password or LoginContext is provided (in constructor) then this field will always be null.


cntxtEstablished

private transient boolean cntxtEstablished
Flag to determine if GSSContext has been established. Users of this class should always check that this field is true before using/trusting the contents of the response.


conn

private transient HttpURLConnection conn
Ref to HTTP URL Connection object after calling connect method. Always call spnego.disconnect() when done using this class.


reqCredDeleg

private transient boolean reqCredDeleg
Request credential to be delegated. Default is false.


autoDisposeCreds

private transient boolean autoDisposeCreds
Determines if the GSSCredentials (if any) used during the connection request should be automatically disposed by this class when finished. Default is true.

Constructor Detail

SpnegoHttpURLConnection

public SpnegoHttpURLConnection(String loginModuleName)
                        throws LoginException
Creates an instance where the LoginContext relies on a keytab file being specified by "java.security.auth.login.config" or where LoginContext relies on tgtsessionkey.

Parameters:
loginModuleName -
Throws:
LoginException

SpnegoHttpURLConnection

public SpnegoHttpURLConnection(GSSCredential creds)
Create an instance where the GSSCredential is specified by the parameter and where the GSSCredential is automatically disposed after use.

Parameters:
creds - credentials to use

SpnegoHttpURLConnection

public SpnegoHttpURLConnection(GSSCredential creds,
                               boolean dispose)
Create an instance where the GSSCredential is specified by the parameter and whether the GSSCredential should be disposed after use.

Parameters:
creds - credentials to use
dispose - true if GSSCredential should be diposed after use

SpnegoHttpURLConnection

public SpnegoHttpURLConnection(String loginModuleName,
                               String username,
                               String password)
                        throws LoginException
Creates an instance where the LoginContext does not require a keytab file. However, the "java.security.auth.login.config" property must still be set prior to instantiating this object.

Parameters:
loginModuleName -
username -
password -
Throws:
LoginException
Method Detail

assertConnected

private void assertConnected()
Throws IllegalStateException if this connection object has not yet created a communications link to the specified URL.


assertNotConnected

private void assertNotConnected()
Throws IllegalStateException if this connection object has already created a communications link to the specified URL.


connect

public HttpURLConnection connect(URL url)
                          throws GSSException,
                                 PrivilegedActionException,
                                 IOException
Opens a communications link to the resource referenced by this URL, if such a connection has not already been established.

This implementation simply calls this objects connect(URL, ByteArrayOutputStream) method but passing in a null for the second argument.

Parameters:
url -
Returns:
an HttpURLConnection object
Throws:
GSSException
PrivilegedActionException
IOException
LoginException
See Also:
URLConnection.connect()

connect

public HttpURLConnection connect(URL url,
                                 ByteArrayOutputStream dooutput)
                          throws GSSException,
                                 PrivilegedActionException,
                                 IOException
Opens a communications link to the resource referenced by this URL, if such a connection has not already been established.

Parameters:
url -
dooutput - optional message/payload to send to server
Returns:
an HttpURLConnection object
Throws:
GSSException
PrivilegedActionException
IOException
LoginException
See Also:
URLConnection.connect()

dispose

private void dispose(GSSContext context)
Logout the LoginContext instance, and call dispose() on GSSCredential if autoDisposeCreds is set to true, and call dispose on the passed-in GSSContext instance.


disconnect

public void disconnect()
Logout and clear request properties.

See Also:
HttpURLConnection.disconnect()

isContextEstablished

public boolean isContextEstablished()
Returns true if GSSContext has been established.

Returns:
true if GSSContext has been established, false otherwise.

assertKeyValue

private void assertKeyValue(String key,
                            String value)
Internal sanity check to validate not null key/value pairs.


addRequestProperty

public void addRequestProperty(String key,
                               String value)
Adds an HTTP Request property.

Parameters:
key - request property name
value - request propery value
See Also:
URLConnection.addRequestProperty(String, String)

setRequestProperty

public void setRequestProperty(String key,
                               String value)
Sets an HTTP Request property.

Parameters:
key - request property name
value - request property value
See Also:
URLConnection.setRequestProperty(String, String)

getGSSContext

private GSSContext getGSSContext(URL url)
                          throws GSSException,
                                 PrivilegedActionException
Returns a GSSContextt for the given url with a default lifetime.

Parameters:
url - http address
Returns:
GSSContext for the given url
Throws:
GSSException
PrivilegedActionException

getErrorStream

public InputStream getErrorStream()
                           throws IOException
Returns an error stream that reads from this open connection.

Returns:
error stream that reads from this open connection
Throws:
IOException
See Also:
HttpURLConnection.getErrorStream()

getHeaderField

public String getHeaderField(int index)
Get header value at specified index.

Parameters:
index -
Returns:
header value at specified index

getHeaderField

public String getHeaderField(String name)
Get header value by header name.

Parameters:
name - name header
Returns:
header value
See Also:
URLConnection.getHeaderField(String)

getHeaderFieldKey

public String getHeaderFieldKey(int index)
Get header field key at specified index.

Parameters:
index -
Returns:
header field key at specified index

getInputStream

public InputStream getInputStream()
                           throws IOException
Returns an input stream that reads from this open connection.

Returns:
input stream that reads from this open connection
Throws:
IOException
See Also:
URLConnection.getInputStream()

getOutputStream

public OutputStream getOutputStream()
                             throws IOException
Returns an output stream that writes to this open connection.

Returns:
output stream that writes to this connections
Throws:
IOException
See Also:
URLConnection.getOutputStream()

getResponseCode

public int getResponseCode()
                    throws IOException
Returns HTTP Status code.

Returns:
HTTP Status Code
Throws:
IOException
See Also:
HttpURLConnection.getResponseCode()

getResponseMessage

public String getResponseMessage()
                          throws IOException
Returns HTTP Status message.

Returns:
HTTP Status Message
Throws:
IOException
See Also:
HttpURLConnection.getResponseMessage()

requestCredDeleg

public void requestCredDeleg(boolean requestDelegation)
Request that this GSSCredential be allowed for delegation.

Parameters:
requestDelegation - true to allow/request delegation

setRequestMethod

public void setRequestMethod(String method)
May override the default GET method.

Parameters:
method -
See Also:
HttpURLConnection.setRequestMethod(String)