Java Tip 46: Use Java 1.2's Authenticator class

Learn to access password-protected URLs with Java 1.2

When surfing the 'Net using your favorite browser you encounter a URL that requires authentication from a proxy or HTTP server and are presented with the all-too-familiar screen demanding your username and password:

Accessing a URL like http://www.lombard.com/cgi-bin/Quotes/quote from a browser is not a problem because you can provide a username and password yourself. But from a Java program, a FileNotFoundException is thrown when you try to read from an InputStream associated with the URL.

User name and password dialog box

With Java 1.0 or 1.1, you can avoid this by posting the appropriate authentication string at connection time, but only if you know beforehand that the URL is protected. (Authorization: Basic username:password, where the basic authentication fields are encoded in base 64.) If you don't forsee that a document is protected, you won't even be able to read the content. (See "Java Tip 47: URL authentication revisited" for the solution to accessing password-protected URLs with Java 1.1 applets and applications.) Thankfully, Java 1.2 adds an Authenticator class to the java.net package that makes accessing password-protected URLs as easy as can be.

Now, in Java 1.2, you simply install an Authenticator, with Authenticator.setDefault(). Then, when authentication is necessary, the installed Authenticator's getPasswordAuthentication() method is called, and you return a PasswordAuthentication instance with the appropriate username and password. It's that easy.

The steps are shown below.

Step 1: Install Authenticator

Authenticator.setDefault (new MyAuthenticator ());

Step 2: Create Authenticator subclass

class MyAuthenticator extends Authenticator {  protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication ("username", "password");
  }
}

The following program shows off this behavior in its entirety, offering its own authentication prompt dialog.

import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
public class URLPassword extends Frame {
  private TextField tf = new TextField();
  private TextArea  ta = new TextArea();
  public URLPassword() {
    super ("URL Password");
    // Install Authenticator
    Authenticator.setDefault (new MyAuthenticator ());
    // Setup screen
    add (tf, BorderLayout.NORTH);
    ta.setEditable(false);
    add (ta, BorderLayout.CENTER);
    tf.addActionListener (new ActionListener() {
      public void actionPerformed (ActionEvent e) {
        String s = tf.getText();
        if (s.length() != 0)
          ta.setText (fetchURL (s));
      }
    });
    addWindowListener (new WindowAdapter() {
      public void windowClosing (WindowEvent e) {
        dispose();
        System.exit(0);
      }
    });
  }
  private String fetchURL (String urlString) {
    StringWriter sw = new StringWriter();
    PrintWriter  pw = new PrintWriter(sw);
    try {
      URL url = new URL (urlString);
      InputStream content = (InputStream)url.getContent();
      BufferedReader in   = 
        new BufferedReader (new InputStreamReader (content));
      String line;
      while ((line = in.readLine()) != null) {
        pw.println (line);
      }
    } catch (MalformedURLException e) {
      pw.println ("Invalid URL");
    } catch (IOException e) {
      pw.println ("Error reading URL");
    }
    return sw.toString();
  }
  public static void main (String args[]) {
    Frame f = new URLPassword();
    f.setSize(300, 300);
    f.setVisible (true);
  }
  class MyAuthenticator extends Authenticator {
    protected PasswordAuthentication getPasswordAuthentication() {
      final Dialog jd = new Dialog (URLPassword.this, "Enter password", true);
      jd.setLayout (new GridLayout (0, 1));
      Label jl = new Label (getRequestingPrompt());
      jd.add (jl);
      TextField username = new TextField();
      username.setBackground (Color.lightGray);
      jd.add (username);
      TextField password = new TextField();
      password.setEchoChar ('*');
      password.setBackground (Color.lightGray);
      jd.add (password);
      Button jb = new Button ("OK");
      jd.add (jb);
      jb.addActionListener (new ActionListener() {
        public void actionPerformed (ActionEvent e) {
          jd.dispose();
        }
      });
      jd.pack();
      jd.setVisible(true);
      return new PasswordAuthentication (username.getText(), password.getText());
    }
  }
}

A follow-up tip - From Luis Blanco Gomez

Line 85 of the code, which is the return argument of the MyAuthenticator class, displays an error:

return new PasswordAuthentication (username.getText(), password.getText());

The compiler will get:

URLPass.java:88: Incompatible type for constructor. Can't convert
java.lang.String to char[].
    return new PasswordAuthentication ( username.getText(), password.getText());

To correct this error you must declare a String variable to hold password.getText(); for example, "String pass = password.getText();", and leave the return line as follows:

return new PasswordAuthentication ( username.getText(), pass.toCharArray());

To test this, you will have to find a URL with a username and password that you know. For Discover Brokerage Direct, anyone can get a free password at the registration desk. Then, try the program with a URL of http://www.lombard.com/cgi-bin/Quotes/quote.

A couple of points worth mentioning: Untrusted applets can install a default Authenticator within appletviewer. What HotJava, Navigator, and Internet Explorer will do is yet to be seen. If you try to change authenticators without the necessary permission, an AccessControlException will be thrown.

John Zukowski is a software mage with MageLang Institute, author of Java AWT Reference from O'Reilly & Associates and Borland's JBuilder: No experience required from Sybex, as well as the Focus on Java guide at the Mining Company.

Learn more about this topic

  • Authenticator documentation http://java.sun.com/products/jdk/1.2/docs/api/java.net.Authenticator.html
  • Swing's JEditorPane class, a simple HTML renderer http://java.sun.com/products/jfc/swingdoc-current/api/com.sun.java.swing.JEditorPane.html
Recommended
Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more