Introduction
Many popular sites require a username and password for access. Some sites, such as the W3C member pages, implement this through HTTP authentication. Others, such as the New York Times website, implement it through cookies and HTML forms. Java’s URL class can access sites that use HTTP authentication, although you’ll of course need to tell it which username and password to use.
Supporting sites that use nonstandard, cookie-based authentication is more challenging, not least because this varies a lot from one site to another. Implementing cookie authentication is hard short of implementing a complete web browser with full HTML forms and cookie support. Accessing sites protected by standard HTTP authentication is much easier.
The Authenticator Class
The java.net package includes an Authenticator class you can use to provide a username and password for sites that protect themselves using HTTP authentication:
public abstract class Authenticator extends Object
Since Authenticator is an abstract class, you must subclass it. Different subclasses may retrieve the information in different ways. For example, a character mode program might just ask the user to type the username and password on System.in. An automated robot might read the username out of an encrypted file.
To make the URL class use the subclass, install it as the default authenticator by passing it to the static Authenticator.setDefault() method:
public static void setDefault(Authenticator a)
For example, if you’ve written an Authenticator subclass named DialogAuthenticator, you’d install it like this:
Authenticator.setDefault(new DialogAuthenticator());
You only need to do this once. From this point forward, when the URL class needs a username and password, it will ask the DialogAuthenticator using Authenticator.requestPasswordAuthentication() method:
public static PasswordAuthentication requestPasswordAuthentication(InetAddress address, int port, String protocol, String prompt, String scheme) throws SecurityException
The address argument is the host for which authentication is required. The port argument is the port on that host, and the protocol argument is the application layer protocol by which the site is being accessed. The HTTP server provides the prompt. It’s typically the name of the realm for which authentication is required. (Some large web servers such as www.ibiblio.org have multiple realms, each of which requires different usernames and passwords.) The scheme is the authentication scheme being used. (Here the word scheme is not being used as a synonym for protocol. Rather, it is an HTTP authentication scheme, typically basic.) Untrusted applets are not allowed to ask the user for a name and password. Trusted applets can do so, but only if they possess the requestPasswordAuthentication Net Permission. Otherwise, Authenticator.requestPasswordAuthentication() throws a SecurityException.
The Authenticator subclass must override the getPasswordAuthentication() method. Inside this method, you collect the username and password from the user or someother source and return it as an instance of the java.net.PasswordAuthentication class:
protected PasswordAuthentication getPasswordAuthentication()
If you don’t want to authenticate this request, return null, and Java will tell the server it doesn’t know how to authenticate the connection. If you submit an incorrect username or password, Java will call getPasswordAuthentication() again to give you another chance to provide the right data. You normally have five tries to get the username and password correct; after that, openStream() throws a ProtocolException. Usernames and passwords are cached within the same virtual machine session. Once you set the correct password for a realm, you shouldn’t be asked for it again unless you’ve
explicitly deleted the password by zeroing out the char array that contains it. You can get more details about the request by invoking any of these methods inherited from the Authenticator superclass:
protected final InetAddress getRequestingSite()
protected final int getRequestingPort()
protected final String getRequestingProtocol()
protected final String getRequestingPrompt()
protected final String getRequestingScheme()
protected final String getRequestingHost()
protected final String getRequestingURL()
protected Authenticator.RequestorType getRequestorType()
These methods either return the information as given in the last call to requestPass wordAuthentication() or return null if that information is not available. (If the port isn’t available, getRequestingPort() returns -1.)
The getRequestingURL() method returns the complete URL for which authentication has been requested—an important detail if a site uses different names and passwords for different files. The getRequestorType() method returns one of the two named constants (i.e., Authenticator.RequestorType.PROXY or Authenticator.Requestor Type.SERVER) to indicate whether the server or the proxy server is requesting the authentication.
The PasswordAuthentication Class
PasswordAuthentication is a very simple final class that supports two read-only properties: username and password. The username is a String. The password is a char array so that the password can be erased when it’s no longer needed. A String would have to wait to be garbage collected before it could be erased, and even then it might still exist somewhere in memory on the local system, possibly even on disk if the block of memory that contained it had been swapped out to virtual memory at one point. Both username and password are set in the constructor:
public PasswordAuthentication(String userName, char[] password)
Each is accessed via a getter method:
public String getUserName()
public char[] getPassword()
The JPasswordField Class
One useful tool for asking users for their passwords in a more or less secure fashion is the JPasswordField component from Swing:
public class JPasswordField extends JTextField
This lightweight component behaves almost exactly like a text field. However, anything the user types into it is echoed as an asterisk. This way, the password is safe from anyone looking over the user’s shoulder at what’s being typed on the screen. JPasswordField also stores the passwords as a char array so that when you’re done with the password you can overwrite it with zeros. It provides the getPassword() method to return this:
public char[] getPassword()
Otherwise, you mostly use the methods it inherits from the JTextField superclass.