Java Tip 47: URL authentication revisited
You're not yet using Java 1.2? Access password-protected URLs with Java 1.1
By John Zukowski, JavaWorld.com, 02/01/98
- Digg
- Reddit
- SlashDot
- Stumble
- del.icio.us
- Technorati
- dzone
In the
last tip, we introduced the following scenario: You're using your favorite browser to surf the 'Net, and you encounter a URL that
requires authentication from a proxy or HTTP server. What you see on the screen is the standard box in which you must enter
your username and password so as to gain access to the site. To refresh your memory, here's what that screen looks like:

From a Java program, you'll find yourself in trouble: When you try to read from an
InputStream associated with the URL, a
FileNotFoundException is thrown. Starting with Java 1.2, you can take advantage of the
Authenticator class, which, as mentioned above, you learned about in Java Tip 46. However, with versions prior to Java 1.2, you need to
know if the URL you want to access is password-protected before you try to read from it. If the URL is protected, you have
to manually configure the username-password response for each URL, so you can properly access the contents. The response is
in the form of what's called an authorization request property. The property gets associated with the
URLConnection for the URL. Once the authorization setting is installed, when you get the URL's contents, the information will be accessible.
The authorization string is of the form "
Authorization: Basic username:password," where the basic authentication fields are encoded in Base64. (A description of the encoding scheme
is found in RFC 1113. An RFC is a "request for comments" document that, basically, describes some kind of Internet standard.
In this case, #1113 describes Message Encipherment and Authentication Procedures. See
Resources below.) To do the encoding, you can use the
BASE64Encoder class in the
sun.misc package, or you can create your own class. To set up this access, you simply have to configure the
URL's
URLConnection to have the proper "Authorization" request property. The following steps describe everything:
Step 1: Create URL
URL url = new URL (urlString);
Step 2: Get username and password for specificURL Step 3: Place in String separated by colon (":")
String userPassword = theUsername + ":" + thePassword;
Step 4: Encode the bytes of the string
String encoding = new sun.misc.BASE64Encoder().encode (userPassword.getBytes());
Step 5: Create a URLConnection from the URL
URLConnection uc = url.openConnection();
Step 6: Set the "Authorization" request property for the URLConnection
uc.setRequestProperty ("Authorization", "Basic " + encoding);
And now, the solution
Accessing a password-protected URL in Java 1.1 is demonstrated in its entirety below, with its own authentication prompt dialog.
The code is as similar as can be to the Java 1.2
Authenticator example provided in Java Tip 46. If you choose to avoid
sun.misc classes, or if this happens to be unavailable on your platform, the source for a converter is included below.
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class Auth11 extends Frame implements ActionListener {
private TextField tf = new TextField();
private TextArea ta = new TextArea();
public void actionPerformed (ActionEvent e) {
String s = tf.getText();
if (s.length() != 0)
ta.setText (fetchURL (s));
}
public Auth11() {
super ("URL11 Password");
// Setup screen
add (tf, BorderLayout.NORTH);
ta.setEditable(false);
add (ta, BorderLayout.CENTER);
tf.addActionListener (this);
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);
// Popup Window to request username/password password
MyAuthenticator ma = new MyAuthenticator();
String userPassword = ma.getPasswordAuthentication(this, url.getHost());
// Encode String
String encoding = new sun.misc.BASE64Encoder().encode (userPassword.getBytes());
// or
// String encoding = Base64Converter.encode (userPassword.getBytes());
// Need to work with URLConnection to set request property
URLConnection uc = url.openConnection();
uc.setRequestProperty ("Authorization", "Basic " + encoding);
InputStream content = (InputStream)uc.getInputStream();
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 Auth11();
f.setSize(300, 300);
f.setVisible (true);
}
class MyAuthenticator {
String getPasswordAuthentication(Frame f, String prompt) {
final Dialog jd = new Dialog (f, "Enter password", true);
jd.setLayout (new GridLayout (0, 1));
Label jl = new Label (prompt);
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 username.getText() + ":" + password.getText();
}
}
}
/*********************************************************************
* BASE 64 encoding of a String or an array of bytes.
*
* See also RFC 1421.
*
* @author
* Unknown
* @author
* David W. Croft
* @version
* 1998-06-08
*********************************************************************/
public class Base64Converter
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
{
public static final char [ ] alphabet = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0 to 7
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 8 to 15
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 16 to 23
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 24 to 31
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 32 to 39
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 40 to 47
'w', 'x', 'y', 'z', '0', '1', '2', '3', // 48 to 55
'4', '5', '6', '7', '8', '9', '+', '/' }; // 56 to 63
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
public static String encode ( String s )
//////////////////////////////////////////////////////////////////////
{
return encode ( s.getBytes ( ) );
}
public static String encode ( byte [ ] octetString )
//////////////////////////////////////////////////////////////////////
{
int bits24;
int bits6;
char [ ] out
= new char [ ( ( octetString.length - 1 ) / 3 + 1 ) * 4 ];
int outIndex = 0;
int i = 0;
while ( ( i + 3 ) <= octetString.length )
{
// store the octets
bits24 = ( octetString [ i++ ] & 0xFF ) << 16;
bits24 |= ( octetString [ i++ ] & 0xFF ) << 8;
bits24 |= ( octetString [ i++ ] & 0xFF ) << 0;
bits6 = ( bits24 & 0x00FC0000 ) >> 18;
out [ outIndex++ ] = alphabet [ bits6 ];
bits6 = ( bits24 & 0x0003F000 ) >> 12;
out [ outIndex++ ] = alphabet [ bits6 ];
bits6 = ( bits24 & 0x00000FC0 ) >> 6;
out [ outIndex++ ] = alphabet [ bits6 ];
bits6 = ( bits24 & 0x0000003F );
out [ outIndex++ ] = alphabet [ bits6 ];
}
if ( octetString.length - i == 2 )
{
// store the octets
bits24 = ( octetString [ i ] & 0xFF ) << 16;
bits24 |= ( octetString [ i + 1 ] & 0xFF ) << 8;
bits6 = ( bits24 & 0x00FC0000 ) >> 18;
out [ outIndex++ ] = alphabet [ bits6 ];
bits6 = ( bits24 & 0x0003F000 ) >> 12;
out [ outIndex++ ] = alphabet [ bits6 ];
bits6 = ( bits24 & 0x00000FC0 ) >> 6;
out [ outIndex++ ] = alphabet [ bits6 ];
// padding
out [ outIndex++ ] = '=';
}
else if ( octetString.length - i == 1 )
{
// store the octets
bits24 = ( octetString [ i ] & 0xFF ) << 16;
bits6 = ( bits24 & 0x00FC0000 ) >> 18;
out [ outIndex++ ] = alphabet [ bits6 ];
bits6 = ( bits24 & 0x0003F000 ) >> 12;
out [ outIndex++ ] = alphabet [ bits6 ];
// padding
out [ outIndex++ ] = '=';
out [ outIndex++ ] = '=';
}
return new String ( out );
}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
}
Remember that using this program will require you to find a URL with a username and password that you know. If you happen
to have acquired a free account from
Discover Brokerage Direct for the
Authenticator tip, you can use it again here. Otherwise, you can get a free password at the
registration desk. Then, as with the last tip, you can try the program with a URL of
http://www.lombard.com/cgi-bin/Quotes/quote.
- Digg
- Reddit
- SlashDot
- Stumble
- del.icio.us
- Technorati
- dzone
Resources
- RFC 1113 (describes encoding format) http://andrew2.andrew.cmu.edu/rfc/rfc1113.html
ThanksBy Anonymous on August 31, 2009, 10:27 amVery good job and explanation
Reply | Read entire comment
using jvm popupBy Anonymous on April 22, 2009, 11:12 amI am loading an applet in web page which is accessed via a proxy. When I am loading it the JVM is throwing a popup for username/password. Is there any way to access...
Reply | Read entire comment
htaccess authenticationBy Anonymous on March 26, 2009, 10:53 pmVery very useful code. Thanks for providing to us. Nanaji
Reply | Read entire comment
View all comments