Ported RFC2617Scheme from Commons HttpClient

git-svn-id: https://svn.apache.org/repos/asf/jakarta/httpcomponents/httpclient/trunk@526919 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2007-04-09 21:10:01 +00:00
parent 4ff37c9c5e
commit a86b2d754a
9 changed files with 700 additions and 5 deletions

View File

@ -134,6 +134,7 @@ public interface AuthScheme {
*
* @return the authorization string
*/
Header authenticate(Credentials credentials, HttpMessage message) throws AuthenticationException;
Header authenticate(Credentials credentials, HttpMessage message)
throws AuthenticationException;
}

View File

@ -32,13 +32,19 @@ package org.apache.http.auth;
/**
* <p>Authentication credentials.</p>
* <p>
* This is just a marker interface, the current implementation has no methods.
* </p>
*
* @author Unascribed
* @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
*
* @version $Revision$ $Date$
*/
public interface Credentials {
/** Returns textual representation of the user credentials, which, for instance,
* could be sent in the {@link HTTPAuth#WWW_AUTH} header.
*
* @return user credentials as a string of text
*/
String toText();
}

View File

@ -0,0 +1,66 @@
/*
* $HeadURL$
* $Revision$
* $Date$
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.auth;
/**
* Constants and static helpers related to the HTTP authentication.
*
* @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
*
* @since 4.0
*/
public final class HTTPAuth {
/**
* The www authenticate challange header.
*/
public static final String WWW_AUTH = "WWW-Authenticate";
/**
* The www authenticate response header.
*/
public static final String WWW_AUTH_RESP = "Authorization";
/**
* The proxy authenticate challange header.
*/
public static final String PROXY_AUTH = "Proxy-Authenticate";
/**
* The proxy authenticate response header.
*/
public static final String PROXY_AUTH_RESP = "Proxy-Authorization";
private HTTPAuth() {
}
}

View File

@ -0,0 +1,93 @@
/*
* $HeadURL$
* $Revision$
* $Date$
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.auth.params;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
/**
* This class implements an adaptor around the {@link HttpParams} interface
* to simplify manipulation of the HTTP authentication specific parameters.
*
* @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
*
* @version $Revision$
*
* @since 4.0
*/
public final class AuthParams {
/**
* Defines the charset to be used when encoding
* {@link org.apache.http.auth.Credentials}. If not defined then the
* {@link #HTTP_ELEMENT_CHARSET} should be used.
* <p>
* This parameter expects a value of type {@link String}.
* </p>
*/
public static final String CREDENTIAL_CHARSET = "http.protocol.credential-charset";
private AuthParams() {
super();
}
/**
* Returns the charset to be used when encoding {@link org.apache.http.auth.Credentials}.
* If not configured the {@link HTTP.DEFAULT_PROTOCOL_CHARSET} is used instead.
*
* @return The charset
*/
public static String getCredentialCharset(final HttpParams params) {
if (params == null) {
throw new IllegalArgumentException("HTTP parameters may not be null");
}
String charset = (String) params.getParameter(CREDENTIAL_CHARSET);
if (charset == null) {
charset = HTTP.DEFAULT_PROTOCOL_CHARSET;
}
return charset;
}
/**
* Sets the charset to be used when encoding {@link org.apache.http.auth.Credentials}.
*
* @param charset The charset
*/
public static void setCredentialCharset(final HttpParams params, final String charset) {
if (params == null) {
throw new IllegalArgumentException("HTTP parameters may not be null");
}
params.setParameter(CREDENTIAL_CHARSET, charset);
}
}

View File

@ -0,0 +1,183 @@
/*
* $HeadURL$
* $Revision$
* $Date$
*
* ====================================================================
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.impl.auth;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.Header;
import org.apache.http.HttpMessage;
import org.apache.http.auth.AuthenticationException;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.HTTPAuth;
import org.apache.http.auth.MalformedChallengeException;
import org.apache.http.auth.params.AuthParams;
import org.apache.http.message.BufferedHeader;
import org.apache.http.util.CharArrayBuffer;
import org.apache.http.util.EncodingUtils;
/**
* <p>
* Basic authentication scheme as defined in RFC 2617.
* </p>
*
* @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
* @author Rodney Waldhoff
* @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
* @author Ortwin Glueck
* @author Sean C. Sullivan
* @author <a href="mailto:adrian@ephox.com">Adrian Sutton</a>
* @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
* @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
*/
public class BasicScheme extends RFC2617Scheme {
/** Whether the basic authentication process is complete */
private boolean complete;
/**
* Default constructor for the basic authetication scheme.
*
* @since 3.0
*/
public BasicScheme() {
super();
this.complete = false;
}
/**
* Returns textual designation of the basic authentication scheme.
*
* @return <code>basic</code>
*/
public String getSchemeName() {
return "basic";
}
/**
* Processes the Basic challenge.
*
* @param challenge the challenge string
*
* @throws MalformedChallengeException is thrown if the authentication challenge
* is malformed
*
* @since 3.0
*/
public void processChallenge(
final Header header) throws MalformedChallengeException {
super.processChallenge(header);
this.complete = true;
}
/**
* Tests if the Basic authentication process has been completed.
*
* @return <tt>true</tt> if Basic authorization has been processed,
* <tt>false</tt> otherwise.
*
* @since 3.0
*/
public boolean isComplete() {
return this.complete;
}
/**
* Returns <tt>false</tt>. Basic authentication scheme is request based.
*
* @return <tt>false</tt>.
*
* @since 3.0
*/
public boolean isConnectionBased() {
return false;
}
/**
* Produces basic authorization header for the given set of {@link Credentials}.
*
* @param credentials The set of credentials to be used for athentication
* @param message The message being authenticated
* @throws InvalidCredentialsException if authentication credentials
* are not valid or not applicable for this authentication scheme
* @throws AuthenticationException if authorization string cannot
* be generated due to an authentication failure
*
* @return a basic authorization string
*
* @since 4.0
*/
public Header authenticate(
final Credentials credentials,
final HttpMessage message) throws AuthenticationException {
if (credentials == null) {
throw new IllegalArgumentException("Credentials may not be null");
}
if (message == null) {
throw new IllegalArgumentException("HTTP message may not be null");
}
String charset = AuthParams.getCredentialCharset(message.getParams());
return authenticate(credentials, charset);
}
/**
* Returns a basic <tt>Authorization</tt> header value for the given
* {@link Credentials} and charset.
*
* @param credentials The credentials to encode.
* @param charset The charset to use for encoding the credentials
*
* @return a basic authorization header
*
* @since 4.0
*/
public static Header authenticate(final Credentials credentials, final String charset) {
if (credentials == null) {
throw new IllegalArgumentException("Credentials may not be null");
}
if (charset == null) {
throw new IllegalArgumentException("charset may not be null");
}
CharArrayBuffer buffer = new CharArrayBuffer(32);
buffer.append(HTTPAuth.WWW_AUTH_RESP);
buffer.append(": ");
buffer.append("Basic ");
byte[] passwd = Base64.encodeBase64(
EncodingUtils.getBytes(credentials.toText(), charset));
buffer.append(passwd, 0, passwd.length);
return new BufferedHeader(buffer);
}
}

View File

@ -0,0 +1,159 @@
/*
* $HeadeURL$
* $Revision$
* $Date$
*
* ====================================================================
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.impl.auth;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.auth.AuthScheme;
import org.apache.http.auth.HTTPAuth;
import org.apache.http.auth.MalformedChallengeException;
import org.apache.http.message.BasicHeaderElement;
import org.apache.http.message.BufferedHeader;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.CharArrayBuffer;
/**
* <p>
* Abstract authentication scheme class that lays foundation for all
* RFC 2617 compliant authetication schemes and provides capabilities common
* to all authentication schemes defined in RFC 2617.
* </p>
*
* @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
*/
public abstract class RFC2617Scheme implements AuthScheme {
/**
* Authentication parameter map.
*/
private Map params = null;
/**
* Default constructor for RFC2617 compliant authetication schemes.
*
* @since 3.0
*/
public RFC2617Scheme() {
super();
}
/**
* Processes the given challenge token. Some authentication schemes
* may involve multiple challenge-response exchanges. Such schemes must be able
* to maintain the state information when dealing with sequential challenges
*
* @param challenge the challenge string
*
* @throws MalformedChallengeException is thrown if the authentication challenge
* is malformed
*
* @since 3.0
*/
public void processChallenge(final Header header) throws MalformedChallengeException {
if (header == null) {
throw new IllegalArgumentException("Header may not be null");
}
if (!header.getName().equalsIgnoreCase(HTTPAuth.WWW_AUTH)) {
throw new MalformedChallengeException("Unexpected header name: " + header.getName());
}
CharArrayBuffer buffer;
int pos;
if (header instanceof BufferedHeader) {
buffer = ((BufferedHeader) header).getBuffer();
pos = ((BufferedHeader) header).getValuePos();
} else {
String s = header.getValue();
if (s == null) {
throw new MalformedChallengeException("Header value is null");
}
buffer = new CharArrayBuffer(s.length());
buffer.append(s);
pos = 0;
}
while (pos < buffer.length() && HTTP.isWhitespace(buffer.charAt(pos))) {
pos++;
}
int beginIndex = pos;
while (pos < buffer.length() && !HTTP.isWhitespace(buffer.charAt(pos))) {
pos++;
}
int endIndex = pos;
String s = buffer.substring(beginIndex, endIndex);
if (!s.equalsIgnoreCase(getSchemeName())) {
throw new MalformedChallengeException("Invalid scheme identifier: " + s);
}
HeaderElement[] elements = BasicHeaderElement.parseAll(buffer, pos, buffer.length());
this.params = new HashMap(elements.length);
for (int i = 0; i < elements.length; i++) {
HeaderElement element = elements[i];
this.params.put(element.getName(), element.getValue());
}
}
/**
* Returns authentication parameters map. Keys in the map are lower-cased.
*
* @return the map of authentication parameters
*/
protected Map getParameters() {
return this.params;
}
/**
* Returns authentication parameter with the given name, if available.
*
* @param name The name of the parameter to be returned
*
* @return the parameter with the given name
*/
public String getParameter(final String name) {
if (name == null) {
throw new IllegalArgumentException("Parameter name may not be null");
}
if (this.params == null) {
return null;
}
return (String) this.params.get(name.toLowerCase());
}
/**
* Returns authentication realm. The realm may not be null.
*
* @return the authentication realm
*/
public String getRealm() {
return getParameter("realm");
}
}

View File

@ -42,7 +42,7 @@ import org.apache.commons.logging.Log;
*
* @since 2.0beta1
*/
class Wire {
public class Wire {
private Log log;

View File

@ -0,0 +1,56 @@
/*
* $HeadURL$
* $Revision$
* $Date$
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.impl.auth;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
public class TestAllAuthImpl extends TestCase {
public TestAllAuthImpl(String testName) {
super(testName);
}
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(TestRFC2617Scheme.suite());
return suite;
}
public static void main(String args[]) {
String[] testCaseName = { TestAllAuthImpl.class.getName() };
junit.textui.TestRunner.main(testCaseName);
}
}

View File

@ -0,0 +1,131 @@
/*
* $HeadURL$
* $Revision$
* $Date$
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.impl.auth;
import org.apache.http.Header;
import org.apache.http.HttpMessage;
import org.apache.http.auth.AuthenticationException;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.HTTPAuth;
import org.apache.http.auth.MalformedChallengeException;
import org.apache.http.message.BasicHeader;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
public class TestRFC2617Scheme extends TestCase {
// ------------------------------------------------------------ Constructor
public TestRFC2617Scheme(String name) {
super(name);
}
// ------------------------------------------------------- TestCase Methods
public static Test suite() {
return new TestSuite(TestRFC2617Scheme.class);
}
static class TestAuthScheme extends RFC2617Scheme {
public Header authenticate(
final Credentials credentials,
final HttpMessage message) throws AuthenticationException {
return null;
}
public String getSchemeName() {
return "test";
}
public boolean isComplete() {
return false;
}
public boolean isConnectionBased() {
return false;
}
}
public void testProcessChallenge() throws Exception {
TestAuthScheme authscheme = new TestAuthScheme();
Header header = new BasicHeader(
HTTPAuth.WWW_AUTH,
"Test realm=\"realm1\", test, test1 = stuff, test2 = \"stuff, stuff\", test3=\"crap");
authscheme.processChallenge(header);
assertEquals("test", authscheme.getSchemeName());
assertEquals("realm1", authscheme.getParameter("realm"));
assertEquals(null, authscheme.getParameter("test"));
assertEquals("stuff", authscheme.getParameter("test1"));
assertEquals("stuff, stuff", authscheme.getParameter("test2"));
assertEquals("\"crap", authscheme.getParameter("test3"));
}
public void testProcessChallengeWithLotsOfBlanks() throws Exception {
TestAuthScheme authscheme = new TestAuthScheme();
Header header = new BasicHeader(HTTPAuth.WWW_AUTH, " Test realm=\"realm1\"");
authscheme.processChallenge(header);
assertEquals("test", authscheme.getSchemeName());
assertEquals("realm1", authscheme.getParameter("realm"));
}
public void testInvalidHeader() throws Exception {
TestAuthScheme authscheme = new TestAuthScheme();
Header header = new BasicHeader("whatever", "Test realm=\"realm1\"");
try {
authscheme.processChallenge(header);
fail("MalformedChallengeException should have been thrown");
} catch (MalformedChallengeException ex) {
//expected
}
}
public void testInvalidHeaderValue() throws Exception {
TestAuthScheme authscheme = new TestAuthScheme();
Header header = new BasicHeader("whatever", "whatever");
try {
authscheme.processChallenge(header);
fail("MalformedChallengeException should have been thrown");
} catch (MalformedChallengeException ex) {
//expected
}
}
}