Name: nt126004 Date: 09/30/2002
FULL PRODUCT VERSION :
C:\ems\spawar\ems\svc\gui\client>java -version
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)
FULL OPERATING SYSTEM VERSION : Windows 2000 sp2
EXTRA RELEVANT SYSTEM CONFIGURATION :
Web server is Netscape Enterprise Server 6.1 running on
same machine.
A DESCRIPTION OF THE PROBLEM :
A GET request is submitted to a servlet running Netscape
Enterprise Server 6.1 (HTTP/1.1) for a realm which has
already been successfully authenticated. A servlet running
within that realm intentionally responds with a 401/WWW-
Authentication response to force a reauthentication. If
the user enters an incorrect login during the
reauthentication, the connection fails and cannot be
reinitialized without restarting the client.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Start the servlet in a restricted realm
2. Start the client and login to the restricted realm
3. Initiate a GET request to the servlet to force
reauthentication in the restricted realm - a login dialog
appears
4. Login incorrectly when prompted - error occurs
EXPECTED VERSUS ACTUAL BEHAVIOR :
Beginning from step 4, the login prompt should appear until
the user successfully reauthenticates or the connection
expires in which case the user should be notified.
Instead, an uncaught exception occurs resulting in a
connection that can no longer be reinitialized without
restarting the client.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.LinkedList.entry(LinkedList.java:356)
at java.util.LinkedList.get(LinkedList.java:299)
at sun.net.www.protocol.http.PathMap.get(AuthenticationInfo.java:355)
at sun.net.www.protocol.http.AuthenticationInfo.getAuth
(AuthenticationInfo.java:176)
at sun.net.www.protocol.http.AuthenticationInfo.getServerAuth
(AuthenticationInfo.java:166)
at sun.net.www.protocol.http.HttpURLConnection.getServerAuthentication
(HttpURLConnection.java:920)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream
(HttpURLConnection.java:600)
at sun.net.www.protocol.http.HttpURLConnection.getHeaderFields
(HttpURLConnection.java:1133)
at TestClient.reauthenticate(TestClient.java:30)
at TestClient.main(TestClient.java:57)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
************************** Client code: **************************************
public class TestClient {
/**
allows reauthentication. Used to update an expired user
token.
*/
public static void reauthenticate(String url)
{
java.net.HttpURLConnection urlConnection = null;
try
{
java.net.URL u = new java.net.URL(url + "?html=authenticate&id=1");
urlConnection = (java.net.HttpURLConnection)u.openConnection();
//prevent login/password from being sent
urlConnection.setRequestProperty("Authorization", "");
urlConnection.setRequestProperty("Cache-Control", "no-cache");
urlConnection.setRequestProperty("Pragma", "no-cache");
urlConnection.connect();
java.util.Map m = urlConnection.getHeaderFields();
java.util.Set s = m.keySet();
java.util.Iterator i = s.iterator();
while(i.hasNext())
{
String key = (String)i.next();
Object value = m.get(key);
System.out.println(key + ": " + value);
}
}
catch(Exception e){e.printStackTrace();}
finally{urlConnection.disconnect();}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
//args[0] must be a reference to a simple html page in a restricted
realm (e.g. /client/index.html)
//args[1] must be a reference to the TestServlet deeper in the
restricted realm (e.g. /client/control/TestServlet)
java.net.URLConnection.setDefaultAllowUserInteraction(true);
java.net.Authenticator.setDefault(new BasicAuthenticator());
javax.swing.JTextPane pane = new javax.swing.JTextPane();
//authenticate in realm first
try{pane.setPage(args[0]);}
catch(java.io.IOException e){}
TestClient t = new TestClient();
//attempt to reauthenticate in the same realm
t.reauthenticate(args[1]);
}
}
************************** Servlet code: **************************************
import java.text.*;
import java.net.*;
import java.awt.*;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class TestServlet extends javax.servlet.http.HttpServlet
{
private Hashtable hotswapHash = new Hashtable();
public synchronized void doGet (HttpServletRequest req, HttpServletResponse
res) throws ServletException, IOException
{
short posit = 0;
String targetUrl = null;
String id = null;
res.setContentType("text/html");
StringTokenizer qryParams = new StringTokenizer(req.getQueryString
(), "&");
while(qryParams.hasMoreTokens())
{
String qryHash = qryParams.nextToken();
if ( (posit = (short)qryHash.indexOf("html=")) != -1)
targetUrl = qryHash.substring(posit+5);
else if ( (posit = (short)qryHash.indexOf("id=")) != -1)
id = qryHash.substring(posit+3);
}
if(targetUrl.equals("authenticate"))
{
/*java.io.File f = new File("c:\\temp\\output.txt");
java.io.FileOutputStream o = new FileOutputStream(f);
StringBuffer b = new StringBuffer();
b.append(
"\n\nRequest Method: " + req.getMethod() +
"\nRequest URI: " + req.getRequestURI() +
"\nRequest Protocol:"+ req.getProtocol());
java.util.Enumeration headerNames = req.getHeaderNames();
while(headerNames.hasMoreElements()) {
String headerName = (String)headerNames.nextElement();
b.append("\n" + headerName + ": " + req.getHeader(headerName));
}
byte output[] = b.toString().getBytes();
o.write(output, (int)f.length(), output.length);
o.close();
*/
//if in reauthenticate hash already, reauthenticate
//with new login
if(hotswapHash.containsKey(id))
{
//remove flag from hash
hotswapHash.remove(id);
//reset id on Access Service by changing the user
//RTS - no only will this reset token but will
//pick up any data changes in the LDAP server
try
{
res.setStatus(res.SC_NO_CONTENT);
System.out.println("succeeded.");
}
catch(Exception e)
{
//return error which will prompt for reauthentication
askForPassword(res);
System.out.println("failed");
}
finally
{
return;
}
}
//else store in reauthenticate hash and prompt for login
else
{
//store flag in hash
hotswapHash.put(id, id);
//return error which will prompt for reauthentication
askForPassword(res);
System.out.print("reauthenticating " + id + "...");
return;
}
}
}
private void askForPassword(HttpServletResponse response)
{
response.setStatus(response.SC_UNAUTHORIZED); // Ie 401
response.setHeader("WWW-Authenticate",
"BASIC realm=\"Client Login\"");
}
}
*************************** Authenticator Code: *******************************
/*
* BasicAuthenticator.java
*
* Created on June 24, 2002, 6:24 PM
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.PasswordAuthentication;
/**
* Extends Authenticator to allow for user login
* @author R. Smudz
*/
public class BasicAuthenticator extends java.net.Authenticator {
private LoginDialog dialog;
/** Creates a new instance of BasicAuthenticator */
public BasicAuthenticator() {
}
protected java.net.PasswordAuthentication getPasswordAuthentication() {
PasswordAuthentication authentication = createLoginDialog();
return authentication;
}
private PasswordAuthentication createLoginDialog() {
if (dialog == null)
dialog = new LoginDialog();
dialog.show();
PasswordAuthentication p = dialog.getAuth();
return p;
}
}
class LoginDialog extends JDialog implements KeyListener, ActionListener
{
private JPanel north, south;
private JLabel nameLabel, passwordLabel, infoLabel;
private JTextField nameTextField;
private JPasswordField passwordField;
private JButton loginButton, cancelButton;
private String username;
private char password[];
private PasswordAuthentication privateAuth;
public LoginDialog()
{
setModal(true);
setTitle("Login Required");
north = new JPanel();
north.setLayout(null);
north.setPreferredSize(new Dimension(277, 110));
nameLabel = new JLabel("Username:", JLabel.LEFT);
nameLabel.setBounds(10, 60, 90, 20);
north.add(nameLabel);
passwordLabel = new JLabel("Password:", JLabel.LEFT);
passwordLabel.setBounds(10, 90, 90, 20);
north.add(passwordLabel);
nameTextField = new JTextField();
nameTextField.setBounds(100, 60, 157, 20);
north.add(nameTextField);
passwordField = new JPasswordField();
passwordField.setBounds(100, 90, 157, 20);
north.add(passwordField);
getContentPane().add(north,BorderLayout.CENTER);
south = new JPanel();
south.setLayout(new FlowLayout(FlowLayout.RIGHT, 10, 10));
loginButton = new JButton("Login");
loginButton.addActionListener(this);
south.add(loginButton);
cancelButton = new JButton("Cancel");
cancelButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
privateAuth = null;
hide();
}
});
south.add(cancelButton);
getContentPane().add(south, BorderLayout.SOUTH);
loginButton.addKeyListener(this);
setDefaultCloseOperation(HIDE_ON_CLOSE);
pack();
//parent frame may not be up so use center of screen
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
setLocation((int)d.getWidth()/2 - getWidth()/2, (int)d.getHeight()/2 -
getHeight()/2 );
}
public void actionPerformed(ActionEvent ae)
{
char[] authArray;
username = nameTextField.getText();
nameTextField.setText("");
password = passwordField.getPassword();
passwordField.setText("");
privateAuth = new PasswordAuthentication(username, password);
// Delete attributes for userID and password
username = "";
password = new String("").toCharArray();
nameTextField.requestFocus();
hide();
}
/**
* Returns the actual PasswordAuthentication,
* which was generated from the login dialog.
*
* @return PasswordAuthentication - actual PasswordAuthentication.
*/
public PasswordAuthentication getAuth()
{
return privateAuth;
}
public void keyPressed(java.awt.event.KeyEvent keyEvent) {
}
public void keyReleased(java.awt.event.KeyEvent keyEvent) {
}
public void keyTyped(java.awt.event.KeyEvent keyEvent) {
if(keyEvent.getKeyCode() == KeyEvent.VK_UNDEFINED || keyEvent.getKeyCode
() == KeyEvent.VK_ENTER)
actionPerformed(null);
}
}
---------- END SOURCE ----------
(Review ID: 164925)
======================================================================
- duplicates
-
JDK-4678055 Basic Authentication fails with multiple realms
-
- Resolved
-