Index: java/org/apache/commons/httpclient/Authenticator.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/Authenticator.java,v retrieving revision 1.41 diff -u -r1.41 Authenticator.java --- java/org/apache/commons/httpclient/Authenticator.java 28 Mar 2003 16:37:49 -0000 1.41 +++ java/org/apache/commons/httpclient/Authenticator.java 3 Apr 2003 10:23:24 -0000 @@ -199,12 +199,17 @@ * @see HttpMethod#addRequestHeader */ private static boolean authenticate(HttpMethod method, HttpState state, - boolean proxy) + boolean proxy) throws HttpException, UnsupportedOperationException { LOG.trace("enter Authenticator.authenticate(HttpMethod, HttpState, " + "Header, String)"); + return authenticate(method, null, state, proxy); + } + private static boolean authenticate(HttpMethod method, HttpConnection conn, + HttpState state, boolean proxy) + throws HttpException, UnsupportedOperationException { String challengeheader = proxy ? PROXY_AUTH : WWW_AUTH; // I REALLY hate doing this, but I need to avoid multiple autorization @@ -240,9 +245,9 @@ LOG.debug("Using " + authscheme.getSchemeName() + " authentication scheme"); } if (proxy) { - return HttpAuthenticator.authenticateProxy(authscheme, method, state); + return HttpAuthenticator.authenticateProxy(authscheme, method, conn, state); } else { - return HttpAuthenticator.authenticate(authscheme, method, state); + return HttpAuthenticator.authenticate(authscheme, method, conn, state); } } Index: java/org/apache/commons/httpclient/HttpMethodBase.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v retrieving revision 1.127 diff -u -r1.127 HttpMethodBase.java --- java/org/apache/commons/httpclient/HttpMethodBase.java 1 Apr 2003 00:25:24 -0000 1.127 +++ java/org/apache/commons/httpclient/HttpMethodBase.java 3 Apr 2003 10:23:38 -0000 @@ -76,7 +76,6 @@ import org.apache.commons.httpclient.cookie.MalformedCookieException; import org.apache.commons.httpclient.cookie.CookiePolicy; import org.apache.commons.httpclient.cookie.CookieSpec; -import org.apache.commons.httpclient.cookie.MalformedCookieException; import org.apache.commons.httpclient.protocol.Protocol; import org.apache.commons.httpclient.util.URIUtil; import org.apache.commons.logging.Log; @@ -1338,7 +1337,7 @@ if (challenges.length > 0) { try { AuthScheme authscheme = HttpAuthenticator.selectAuthScheme(challenges); - HttpAuthenticator.authenticate(authscheme, this, state); + HttpAuthenticator.authenticate(authscheme, this, conn, state); } catch (HttpException e) { // log and move on if (LOG.isErrorEnabled()) { @@ -1485,7 +1484,7 @@ if (challenges.length > 0) { try { AuthScheme authscheme = HttpAuthenticator.selectAuthScheme(challenges); - HttpAuthenticator.authenticateProxy(authscheme, this, state); + HttpAuthenticator.authenticateProxy(authscheme, this, conn, state); } catch (HttpException e) { // log and move on if (LOG.isErrorEnabled()) { @@ -2340,11 +2339,11 @@ switch (statusCode) { case HttpStatus.SC_UNAUTHORIZED: removeRequestHeader(HttpAuthenticator.WWW_AUTH_RESP); - authenticated = HttpAuthenticator.authenticate(authscheme, this, state); + authenticated = HttpAuthenticator.authenticate(authscheme, this, conn, state); break; case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED: removeRequestHeader(HttpAuthenticator.PROXY_AUTH_RESP); - authenticated = HttpAuthenticator.authenticateProxy(authscheme, this, state); + authenticated = HttpAuthenticator.authenticateProxy(authscheme, this, conn, state); break; } } catch (AuthenticationException e) { Index: java/org/apache/commons/httpclient/HttpState.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpState.java,v retrieving revision 1.18 diff -u -r1.18 HttpState.java --- java/org/apache/commons/httpclient/HttpState.java 27 Mar 2003 20:58:27 -0000 1.18 +++ java/org/apache/commons/httpclient/HttpState.java 3 Apr 2003 10:23:42 -0000 @@ -64,7 +64,6 @@ package org.apache.commons.httpclient; import java.util.ArrayList; -import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -378,7 +377,6 @@ this.cookiePolicy = policy; } - /** * Set the Credentials for the given authentication realm. * @@ -390,40 +388,135 @@ *
* Any previous credentials for this realm will be overwritten.
*
+ * @deprecated This method does not distinguish between realms with the
+ * same name on different hosts. Use
+ * {@link HttpState#setCredentials(String, Credentials)} instead.
+ *
* @param realm the authentication realm
* @param credentials the authentication credentials for the given realm
*
- * @see #getCredentials(String)
- * @see #setProxyCredentials(String, Credentials)
+ * @see #getCredentials(String, String)
+ * @see #setProxyCredentials(String, String, Credentials)
*
*/
+
public synchronized void setCredentials(String realm, Credentials credentials) {
LOG.trace("enter HttpState.setCredentials(String, Credentials)");
- credMap.put(realm, credentials);
+ setCredentials(realm, null, credentials);
+ }
+
+ /** Sets the credentials for realm on host.
+ * with no host.
+ *
+ * When realm is null, I'll use the given
+ * credentials when no other {@link Credentials} have
+ * been supplied for the given challenging realm.
+ * (I.e., use a null realm to set the "default"
+ * credentials.)
+ *
+ * Any previous credentials for this realm will be overwritten.
+ *
+ * @param realm the authentication realm
+ * @param host the host the realm belongs to
+ * @param credentials the authentication credentials for the given realm.
+ *
+ * @see #getCredentials(String, String)
+ * @see #setProxyCredentials(String, String, Credentials)
+ */
+
+ public synchronized void setCredentials(String realm, String host, Credentials credentials) {
+ LOG.trace(
+ "enter HttpState.setCredentials(String realm, String host, Credentials credentials)");
+ credMap.put(host + realm, credentials);
+ /*
+ if (host != null) {
+ if (realm == null) {
+ credMap.put(host.toLowerCase(), credentials);
+ } else {
+ credMap.put(host.toLowerCase() + realm, credentials);
+ }
+ } else {
+ credMap.put(realm, credentials);
+ }*/
+ }
+
+ /**
+ * Get the Credentials for the given authentication realm.
+ *
+ * If the realm exists on host, return the coresponding credentials.
+ * If the host exists with a null realm, return the corresponding
+ * credentials.
+ * If the realm exists with a null host, return the
+ * corresponding credentials. If the realm does not exist, return
+ * the default Credentials. If there are no default credentials, return
+ * null.
+ *
+ * @param realm the authentication realm
+ * @param host the host the realm is on
+ * @return the credentials
+ *
+ * @see #setCredentials(String, String, Credentials)
+ *
+ */
+
+ public synchronized Credentials getCredentials(String realm, String host) {
+ LOG.trace("enter HttpState.getCredentials(String, String");
+ String entry = host + realm;
+ Credentials creds = (Credentials) credMap.get(entry);
+ if (creds == null && host != null && realm != null) {
+ entry = host + null;
+ creds = (Credentials) credMap.get(entry);
+ if (creds == null) {
+ entry = null + realm;
+ creds = (Credentials) credMap.get(entry);
+ }
+ }
+
+ if (creds == null) {
+ // We use this instead of just null as it avoids the need for logic in setCredentials
+ entry = "" + null + null;
+ creds = (Credentials) credMap.get(entry);
+ }
+ /*Credentials creds = null;
+ if (host != null) {
+ creds = (Credentials) credMap.get(host.toLowerCase() + realm);
+ if (creds == null) {
+ creds = (Credentials) credMap.get(host.toLowerCase());
+ }
+ }
+ if (creds == null) {
+ creds = (Credentials) credMap.get(realm);
+ if (creds == null) {
+ creds = (Credentials) credMap.get(null);
+ }
+ }*/
+ return creds;
}
-
/**
* Get the Credentials for the given authentication realm.
*
- * If the realm exists, return the coresponding credentials. If the
- * realm does not exist, return the default Credentials. If there is
- * no default credentials, return null.
+ * If the realm exists on host, return the coresponding credentials.
+ * If the realm exists with a null host, return the
+ * corresponding credentials. If the realm does not exist, return
+ * the default Credentials. If there is no default credentials, return
+ * null.
*
+ * @deprecated This method does not distinguish between realms on different
+ * servers with the same name. Use {@link #getCredentials(String, String)}
+ * instead.
+ *
* @param realm the authentication realm
* @return the credentials
*
- * @see #setCredentials(String, Credentials)
+ * @see #setCredentials(String, String, Credentials)
*
*/
+
public synchronized Credentials getCredentials(String realm) {
LOG.trace("enter HttpState.getCredentials(String)");
- Credentials creds = (Credentials) credMap.get(realm);
- if (creds == null) {
- creds = (Credentials) credMap.get(null);
- }
- return creds;
+ return getCredentials(realm, null);
}
/**
@@ -438,6 +531,10 @@
*
* Any previous credentials for this realm will be overwritten.
*
+ * @depreciated This method does not differentiate between realms with
+ * the same name on different servers. Use
+ * {@link #setProxyCredentials(String, String, Credentials)} instead.
+ *
* @param realm the authentication realm
* @param credentials the authentication credentials for the given realm
*
@@ -445,11 +542,44 @@
* @see #setCredentials(String, Credentials)
*
*/
+
public synchronized void setProxyCredentials(String realm, Credentials credentials) {
LOG.trace("enter HttpState.setProxyCredentials(String, credentials)");
- proxyCred.put(realm, credentials);
+ setProxyCredentials(realm, null, credentials);
+ }
+
+ /**
+ * Set the for the proxy with the given authentication realm.
+ *
+ * When realm and host are null, I'll use the given
+ * credentials when no other {@link Credentials} have
+ * been supplied for the given challenging realm.
+ * (I.e., use a null realm to set the "default"
+ * credentials.) Realms rarely make much sense with proxies, so
+ * null is normally a good choice here.
+ *
+ * Any previous credentials for this realm will be overwritten.
+ *
+ * @param realm the authentication realm
+ * @param credentials the authentication credentials for the given realm
+ *
+ * @see #getProxyCredentials(String)
+ * @see #setCredentials(String, Credentials)
+ *
+ */
+
+ public synchronized void setProxyCredentials(String realm, String proxyHost, Credentials credentials) {
+ LOG.trace("enter HttpState.setProxyCredentials(String, String, Credentials");
+ if (proxyHost != null) {
+ if (realm == null) {
+ proxyCred.put(proxyHost.toLowerCase(), credentials);
+ } else {
+ proxyCred.put(proxyHost.toLowerCase() + realm, credentials);
+ }
+ } else {
+ proxyCred.put(realm, credentials);
+ }
}
-
/**
* Get the Credentials for the proxy with the given authentication realm.
@@ -457,19 +587,58 @@
* If the realm exists, return the coresponding credentials. If the
* realm does not exist, return the default Credentials. If there is
* no default credentials, return null.
+ *
+ * @deprecated This method does not distinguish between realms on different hosts.
+ * Use {@link #getProxyCredentials(String, String)} instead.
*
* @param realm the authentication realm
* @return the credentials
- * @see #setProxyCredentials
+ * @see #setProxyCredentials(String, String, Credentials)
*/
+
public synchronized Credentials getProxyCredentials(String realm) {
LOG.trace("enter HttpState.getProxyCredentials(String)");
- Credentials creds = (Credentials) proxyCred.get(realm);
- if (creds == null) {
- creds = (Credentials) proxyCred.get(null);
- }
- return creds;
+ return getProxyCredentials(realm, null);
}
+
+ /**
+ * Get the Credentials for the proxy with the given authentication realm on the given
+ * host.
+ *
+ * If the realm exists on host, return the coresponding credentials.
+ * If the host exists with a null realm, return the corresponding
+ * credentials.
+ * If the realm exists with a null host, return the
+ * corresponding credentials. If the realm does not exist, return
+ * the default Credentials. If there are no default credentials, return
+ * null.
+ *
+ * @deprecated This method does not distinguish between realms on different hosts.
+ * Use {@link #getProxyCredentials(String, String)} instead.
+ *
+ * @param realm the authentication realm
+ * @param host the host the realm is on
+ * @return the credentials
+ * @see #setProxyCredentials(String, String, Credentials)
+ */
+
+ public synchronized Credentials getProxyCredentials(String realm, String proxyHost) {
+ LOG.trace("enter HttpState.getCredentials(String, String");
+ Credentials creds = null;
+ if (proxyHost != null) {
+ creds = (Credentials) proxyCred.get(proxyHost.toLowerCase() + realm);
+ if (creds == null) {
+ creds = (Credentials) proxyCred.get(proxyHost.toLowerCase());
+ }
+ }
+ if (creds == null) {
+ creds = (Credentials) proxyCred.get(realm);
+ if (creds == null) {
+ creds = (Credentials) proxyCred.get(null);
+ }
+ }
+ return creds;
+ }
/**
* Return a string representation of this object.
Index: java/org/apache/commons/httpclient/auth/HttpAuthenticator.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/auth/HttpAuthenticator.java,v
retrieving revision 1.1
diff -u -r1.1 HttpAuthenticator.java
--- java/org/apache/commons/httpclient/auth/HttpAuthenticator.java 27 Mar 2003 20:58:27 -0000 1.1
+++ java/org/apache/commons/httpclient/auth/HttpAuthenticator.java 3 Apr 2003 10:23:48 -0000
@@ -62,6 +62,7 @@
import java.util.Map;
import java.util.HashMap;
import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpConnection;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HttpState;
@@ -246,10 +247,30 @@
return doAuthenticateDefault(method, state, true);
}
+ /**
+ * Attempt to provide authentication credentials
+ * to the given method in the given state using
+ * the given authentication scheme.
+ *
+ * @param authscheme the authentication scheme to use
+ * @param method the HttpMethod which requires authentication
+ * @param conn the connection being used
+ * @param state the HttpState object providing Credentials
+ *
+ * @return true if an authentication response header
+ * was added
+ *
+ * @throws AuthenticationException when a parsing or other error occurs
- private static boolean doAuthenticate(AuthScheme authscheme, HttpMethod method, HttpState state,
- boolean proxy)
+ * @see HttpState#setCredentials(String, String, Credentials)
+ */
+ private static boolean doAuthenticate(AuthScheme authscheme, HttpMethod method, HttpConnection conn,
+ HttpState state, boolean proxy)
throws AuthenticationException {
+ String host = null;
+ if (conn != null) {
+ host = proxy ? conn.getProxyHost() : conn.getHost();
+ }
if (authscheme == null) {
throw new IllegalArgumentException("Authentication scheme may not be null");
}
@@ -273,8 +294,9 @@
LOG.debug("Using '" + realm + "' authentication realm");
}
}
+
Credentials credentials = proxy ?
- state.getProxyCredentials(realm) : state.getCredentials(realm);
+ state.getProxyCredentials(realm, host) : state.getCredentials(realm, host);
if (credentials == null) {
throw new AuthenticationException(
"No credentials available for the " + authscheme.getSchemeName() +
@@ -308,8 +330,29 @@
*/
public static boolean authenticate(AuthScheme authscheme, HttpMethod method, HttpState state)
throws AuthenticationException {
+ return authenticate(authscheme, method, null, state);
+ }
+
+ /**
+ * Attempt to provide requisite authentication credentials to the
+ * given method in the given state using the given
+ * authentication scheme and host.
+ *
+ * @param authscheme The authentication scheme to be used
+ * @param method The HttpMethod which requires authentication
+ * @param conn The connection being used
+ * @param state The HttpState object providing Credentials
+ *
+ * @return true if the Authenticate response header was added
+ *
+ * @throws AuthenticationException when a parsing or other error occurs
+
+ * @see HttpState#setCredentials(String,Credentials)
+ */
+ public static boolean authenticate(AuthScheme authscheme, HttpMethod method, HttpConnection conn,
+ HttpState state) throws AuthenticationException {
LOG.trace("enter HttpAuthenticator.authenticate(AuthScheme, HttpMethod, HttpState)");
- return doAuthenticate(authscheme, method, state, false);
+ return doAuthenticate(authscheme, method, conn, state, false);
}
@@ -320,6 +363,7 @@
*
* @param authscheme The authentication scheme to be used
* @param method the HttpMethod which requires authentication
+ * @param conn the HttpConnection being used
* @param state the HttpState object providing Credentials
*
* @return true if the Proxy-Authenticate response header
@@ -329,9 +373,9 @@
* @see HttpState#setCredentials(String,Credentials)
*/
- public static boolean authenticateProxy(AuthScheme authscheme, HttpMethod method, HttpState state)
+ public static boolean authenticateProxy(AuthScheme authscheme, HttpMethod method, HttpConnection conn, HttpState state)
throws AuthenticationException {
LOG.trace("enter HttpAuthenticator.authenticateProxy(AuthScheme, HttpMethod, HttpState)");
- return doAuthenticate(authscheme, method, state, true);
+ return doAuthenticate(authscheme, method, conn, state, true);
}
}
Index: test/org/apache/commons/httpclient/TestAuthenticator.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestAuthenticator.java,v
retrieving revision 1.23
diff -u -r1.23 TestAuthenticator.java
--- test/org/apache/commons/httpclient/TestAuthenticator.java 28 Mar 2003 16:37:50 -0000 1.23
+++ test/org/apache/commons/httpclient/TestAuthenticator.java 3 Apr 2003 10:23:54 -0000
@@ -666,5 +666,61 @@
}
-
+ // --------------------------------- Test Methods for Selecting Credentials
+
+ public void testDefaultCredentials() throws Exception {
+ HttpState state = new HttpState();
+ Credentials expected = new UsernamePasswordCredentials("name", "pass");
+ state.setCredentials(null, expected);
+ Credentials got = state.getCredentials("realm", "host");
+ assertEquals(got, expected);
+ }
+
+ public void testRealmCredentials() throws Exception {
+ HttpState state = new HttpState();
+ Credentials expected = new UsernamePasswordCredentials("name", "pass");
+ state.setCredentials("realm", expected);
+ Credentials got = state.getCredentials("realm", "host");
+ assertEquals(expected, got);
+ }
+
+ public void testHostCredentials() throws Exception {
+ HttpState state = new HttpState();
+ Credentials expected = new UsernamePasswordCredentials("name", "pass");
+ state.setCredentials(null, "host", expected);
+ Credentials got = state.getCredentials("realm", "host");
+ assertEquals(expected, got);
+ }
+
+ public void testBothCredentials() throws Exception {
+ HttpState state = new HttpState();
+ Credentials expected = new UsernamePasswordCredentials("name", "pass");
+ state.setCredentials("realm", "host", expected);
+ Credentials got = state.getCredentials("realm", "host");
+ assertEquals(expected, got);
+ }
+
+ public void testWrongHostCredentials() throws Exception {
+ HttpState state = new HttpState();
+ Credentials expected = new UsernamePasswordCredentials("name", "pass");
+ state.setCredentials(null, "host1", expected);
+ Credentials got = state.getCredentials("realm", "host2");
+ assertNotSame(expected, got);
+ }
+
+ public void testWrongRealmCredentials() throws Exception {
+ HttpState state = new HttpState();
+ Credentials cred = new UsernamePasswordCredentials("name", "pass");
+ state.setCredentials("realm1", "host", cred);
+ Credentials got = state.getCredentials("realm2", "host");
+ assertNotSame(cred, got);
+ }
+
+ public void testRealmSpoof() throws Exception {
+ HttpState state = new HttpState();
+ Credentials cred = new UsernamePasswordCredentials("name", "pass");
+ state.setCredentials(null, "admin.apache.org", cred);
+ Credentials got = state.getCredentials("admin.apache.org", null);
+ assertNotSame(cred, got);
+ }
}