Http Authentication |
Documentation Contents |
Generally, all authentication schemes work with both proxies and servers. Some (basic and digest) can be used simultaneously with proxies and servers. See below for how to distinguish between proxy and server authentication.
getPasswordAuthentication()
method. Note, the method is not abstract, and the default implementation
does nothing. The following is a minimal example:
class MyAuthenticator extends Authenticator { public PasswordAuthentication getPasswordAuthentication () { return new PasswordAuthentication ("user", "pass1".toCharArray()); } }
This simple example returns the username "user" and the password "pass1" for every HTTP authentication interaction. A more realistic example would use the other methods of java.net.Authenticator to get more information about the HTTP request that needs to be authenticated. Any of the following methods may be called by the implementation of getPasswordAuthentication() in order to decide how to handle each request for credentials.
Authenticator.setDefault (authinstance);
where authinstance
is an instance of the declared
implementation class. If this
is not called, then authentication is disabled, and server authentication
errors will be returned to user code via IOException objects. Once installed,
the http implementation will try to authenticate automatically where possible
(via cached credentials, or credentials that can be acquired from the
system). If the correct credentials are not available then the user's
authenticator is invoked to provide them.
If the user needs to ensure that a particular scheme is used, then the following system property can be set to modify the default behavior.
-Dhttp.auth.preference="scheme"
-D is specified if the property is being set on the command line. "http.auth.preference" is the property name, and scheme is the name of the scheme to use. If the server does not include this scheme in its list of proposed schemes, then the default choice is made.
The getRequestingPrompt() method returns the Basic authentication realm as provided by the server.
-Dhttp.auth.digest.validateServer="true" -Dhttp.auth.digest.validateProxy="true"
The getRequestingPrompt() method returns the Digest authentication realm as provided by the server.
On Microsoft Windows platforms, NTLM authentication attempts to acquire the user credentials from the system without prompting the user's authenticator object. If these credentials are not accepted by the server then the user's authenticator will be called.
Because the Authenticator class was defined prior to NTLM being supported, it was not possible to add support in the API for the NTLM domain field. There are three options for specifying the domain:
java.security.krb5.conf
. For example:
java -Djava.security.krb5.conf=krb5.conf \ -Djavax.security.auth.useSubjectCredsOnly=false \ ClassName
com.sun.security.jgss.krb5.initiate
.
spnegoLogin.conf
:
com.sun.security.jgss.krb5.initiate { com.sun.security.auth.module.Krb5LoginModule required useTicketCache=true; };and run java with:
java -Djava.security.krb5.conf=krb5.conf \ -Djava.security.auth.login.config=spnegoLogin.conf \ -Djavax.security.auth.useSubjectCredsOnly=false \ ClassName
java.net.Authenticator
to feed username and password to
the HTTP SPNEGO module if they are needed (i.e. there is no credential
cache available). The only authentication information needed to be
checked in your Authenticator is the scheme which can be retrieved
with getRequestingScheme()
. The value should be "Negotiate".
This means your Authenticator implementation will look like:
class MyAuthenticator extends Authenticator { public PasswordAuthentication getPasswordAuthentication () { if (getRequestingScheme().equalsIgnoreCase("negotiate")) { String krb5user; char[] krb5pass; // get krb5user and krb5pass in your own way .... return (new PasswordAuthentication (krb5user, krb5pass)); } else { .... } } }Attention : According to the specification of
java.net.Authenticator
,
it's designed to get the username and password at the same
time, so do not specify principal=xxx
in the JAAS config file.
http.auth.preference
to
denote that a certain scheme should always be used as long as the
server request for it. You can use "SPNEGO" or "Kerberos" for this
system property. "SPNEGO" means you prefer to response the Negotiate
scheme using the GSS/SPNEGO mechanism; "Kerberos" means you prefer
to response the Negotiate scheme using the GSS/Kerberos mechanism.
Normally, when authenticating against a Microsoft product, you can
use "SPNEGO". The value "Kerberos" also works for Microsoft servers.
It's only needed when you encounter a server which knows Negotiate
but doesn't know about SPNEGO.
If http.auth.preference
is not set, the internal order choosen is:
http.auth.preference
is set to SPNEGO or Kerberos, then
we assume you only want to try the Negotiate scheme even if it fails.
we won't fallback to any other scheme and your program will result in
throwing an IOException
saying it receives a 401 or 407 error from
the HTTP response.
You need to prepare these files to get the protected file:
Code listing for RunHttpSpnego.java
import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.Authenticator; import java.net.PasswordAuthentication; import java.net.URL; public class RunHttpSpnego { static final String kuser = "username"; // your account name static final String kpass = "password"; // your password for the account static class MyAuthenticator extends Authenticator { public PasswordAuthentication getPasswordAuthentication() { // I haven't checked getRequestingScheme() here, since for NTLM // and Negotiate, the usrname and password are all the same. System.err.println("Feeding username and password for " + getRequestingScheme()); return (new PasswordAuthentication(kuser, kpass.toCharArray())); } } public static void main(String[] args) throws Exception { Authenticator.setDefault(new MyAuthenticator()); URL url = new URL(args[0]); InputStream ins = url.openConnection().getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(ins)); String str; while((str = reader.readLine()) != null) System.out.println(str); } } |
Code listing for krb5.conf
[libdefaults] default_realm = AD.LOCAL [realms] AD.LOCAL = { kdc = kdc.ad.local } |
Code listing for login.conf
com.sun.security.jgss.krb5.initiate { com.sun.security.auth.module.Krb5LoginModule required doNotPrompt=false useTicketCache=true; }; |
Then, compile RunHttpSpnego.java
and run:
java -Djava.security.krb5.conf=krb5.conf \ -Djava.security.auth.login.config=login.conf \ -Djavax.security.auth.useSubjectCredsOnly=false \ RunHttpSpnego \ http://www.ad.local/hello/hello.html
You will see:
Feeding username and password for Negotiate <h1>Hello, You got me!</h1>
In fact, if you are running on a Windows machine as a domain user, or, you are
running on a Linux or Solaris machine that has already issued the kinit
command and
got the credential cache. The class MyAuthenticator
will be completely
ignored, and the output will be simply
<h1>Hello, You got me!</h1>which shows the username and password are not consulted. This is the so-called Single Sign-On. Also, You can just run
java RunHttpSpnego \ http://www.ad.local/hello/hello.htmlto see how the fallback is done, in which case you will see
Feeding username and password for ntlm <h1>Hello, You got me!</h1>
Copyright
© 2006 Sun Microsystems, Inc.
All Rights Reserved.
|
Java Software |