AuthScheme API changes; User credentials made optional for those schemes that do not require them
git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1692371 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
e7190e7177
commit
d3bcbedec7
|
@ -29,18 +29,13 @@ package org.apache.http.client.fluent;
|
|||
import java.io.IOException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.auth.AuthChallenge;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.ChallengeType;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.auth.MalformedChallengeException;
|
||||
import org.apache.http.auth.NTCredentials;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.client.AuthCache;
|
||||
|
@ -151,12 +146,14 @@ public class Executor {
|
|||
}
|
||||
|
||||
public Executor authPreemptive(final HttpHost host) {
|
||||
final BasicScheme basicScheme = new BasicScheme();
|
||||
try {
|
||||
basicScheme.processChallenge(ChallengeType.TARGET, new AuthChallenge("basic", null, Collections.<NameValuePair>emptyList()));
|
||||
} catch (final MalformedChallengeException ignore) {
|
||||
if (this.credentialsStore != null) {
|
||||
final Credentials credentials = this.credentialsStore.getCredentials(new AuthScope(host));
|
||||
if (credentials == null) {
|
||||
final BasicScheme basicScheme = new BasicScheme();
|
||||
basicScheme.initPreemptive(credentials);
|
||||
this.authCache.put(host, basicScheme);
|
||||
}
|
||||
}
|
||||
this.authCache.put(host, basicScheme);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -168,12 +165,14 @@ public class Executor {
|
|||
}
|
||||
|
||||
public Executor authPreemptiveProxy(final HttpHost proxy) {
|
||||
final BasicScheme basicScheme = new BasicScheme();
|
||||
try {
|
||||
basicScheme.processChallenge(ChallengeType.PROXY, new AuthChallenge("basic", null, Collections.<NameValuePair>emptyList()));
|
||||
} catch (final MalformedChallengeException ignore) {
|
||||
if (this.credentialsStore != null) {
|
||||
final Credentials credentials = this.credentialsStore.getCredentials(new AuthScope(proxy));
|
||||
if (credentials == null) {
|
||||
final BasicScheme basicScheme = new BasicScheme();
|
||||
basicScheme.initPreemptive(credentials);
|
||||
this.authCache.put(proxy, basicScheme);
|
||||
}
|
||||
}
|
||||
this.authCache.put(proxy, basicScheme);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,10 +65,10 @@ public interface HttpCacheStorage {
|
|||
void removeEntry(String key) throws IOException;
|
||||
|
||||
/**
|
||||
* Atomically applies the given callback to update an existing cache
|
||||
* Atomically applies the given callback to processChallenge an existing cache
|
||||
* entry under a given key.
|
||||
* @param key indicates which entry to modify
|
||||
* @param callback performs the update; see
|
||||
* @param callback performs the processChallenge; see
|
||||
* {@link HttpCacheUpdateCallback} for details, but roughly the
|
||||
* callback expects to be handed the current entry and will return
|
||||
* the new value for the entry.
|
||||
|
|
|
@ -28,7 +28,7 @@ package org.apache.http.client.cache;
|
|||
|
||||
/**
|
||||
* Signals that {@link HttpCacheStorage} encountered an error performing an
|
||||
* update operation.
|
||||
* processChallenge operation.
|
||||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
|
|
|
@ -165,7 +165,7 @@ class BasicHttpCache implements HttpCache {
|
|||
try {
|
||||
storage.updateEntry(parentURI, callback);
|
||||
} catch (final HttpCacheUpdateException e) {
|
||||
log.warn("Could not update key [" + parentURI + "]", e);
|
||||
log.warn("Could not processChallenge key [" + parentURI + "]", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,7 @@ class BasicHttpCache implements HttpCache {
|
|||
try {
|
||||
storage.updateEntry(parentCacheKey, callback);
|
||||
} catch (final HttpCacheUpdateException e) {
|
||||
log.warn("Could not update key [" + parentCacheKey + "]", e);
|
||||
log.warn("Could not processChallenge key [" + parentCacheKey + "]", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ public class CacheConfig implements Cloneable {
|
|||
public final static int DEFAULT_MAX_CACHE_ENTRIES = 1000;
|
||||
|
||||
/** Default setting for the number of retries on a failed
|
||||
* cache update
|
||||
* cache processChallenge
|
||||
*/
|
||||
public final static int DEFAULT_MAX_UPDATE_RETRIES = 1;
|
||||
|
||||
|
@ -234,7 +234,7 @@ public class CacheConfig implements Cloneable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the number of times to retry a cache update on failure
|
||||
* Returns the number of times to retry a cache processChallenge on failure
|
||||
*/
|
||||
public int getMaxUpdateRetries(){
|
||||
return maxUpdateRetries;
|
||||
|
@ -400,7 +400,7 @@ public class CacheConfig implements Cloneable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the number of times to retry a cache update on failure
|
||||
* Sets the number of times to retry a cache processChallenge on failure
|
||||
*/
|
||||
public Builder setMaxUpdateRetries(final int maxUpdateRetries) {
|
||||
this.maxUpdateRetries = maxUpdateRetries;
|
||||
|
|
|
@ -48,7 +48,7 @@ import org.apache.http.util.Args;
|
|||
/**
|
||||
* Update a {@link HttpCacheEntry} with new or updated information based on the latest
|
||||
* 304 status response from the Server. Use the {@link HttpResponse} to perform
|
||||
* the update.
|
||||
* the processChallenge.
|
||||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
|
|
|
@ -712,7 +712,7 @@ public class CachingExec implements ClientExecChain {
|
|||
responseEntry = responseCache.updateVariantCacheEntry(target, conditionalRequest,
|
||||
matchedEntry, backendResponse, requestDate, responseDate, matchingVariant.getCacheKey());
|
||||
} catch (final IOException ioe) {
|
||||
log.warn("Could not update cache entry", ioe);
|
||||
log.warn("Could not processChallenge cache entry", ioe);
|
||||
} finally {
|
||||
backendResponse.close();
|
||||
}
|
||||
|
@ -726,7 +726,7 @@ public class CachingExec implements ClientExecChain {
|
|||
try {
|
||||
responseCache.reuseVariantEntryFor(target, request, matchingVariant);
|
||||
} catch (final IOException ioe) {
|
||||
log.warn("Could not update cache entry to reuse variant", ioe);
|
||||
log.warn("Could not processChallenge cache entry to reuse variant", ioe);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ public class DefaultFailureCache implements FailureCache {
|
|||
*
|
||||
* In case there is a lot of contention on that identifier, a thread
|
||||
* might starve. Thus it gives up after a certain number of failed
|
||||
* update tries.
|
||||
* processChallenge tries.
|
||||
*/
|
||||
for (int i = 0; i < MAX_UPDATE_TRIES; i++) {
|
||||
final FailureCacheValue oldValue = storage.get(identifier);
|
||||
|
|
|
@ -159,7 +159,7 @@ interface HttpCache {
|
|||
* @param target host of the upstream client request
|
||||
* @param req request sent by upstream client
|
||||
* @param variant variant cache entry to reuse
|
||||
* @throws IOException may be thrown during cache update
|
||||
* @throws IOException may be thrown during cache processChallenge
|
||||
*/
|
||||
void reuseVariantEntryFor(HttpHost target, final HttpRequest req,
|
||||
final Variant variant) throws IOException;
|
||||
|
|
|
@ -156,6 +156,6 @@ public class EhcacheHttpCacheStorage implements HttpCacheStorage {
|
|||
}
|
||||
}
|
||||
}while(numRetries <= maxUpdateRetries);
|
||||
throw new HttpCacheUpdateException("Failed to update");
|
||||
throw new HttpCacheUpdateException("Failed to processChallenge");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -268,6 +268,6 @@ public class MemcachedHttpCacheStorage implements HttpCacheStorage {
|
|||
}
|
||||
} while (numRetries <= maxUpdateRetries);
|
||||
|
||||
throw new HttpCacheUpdateException("Failed to update");
|
||||
throw new HttpCacheUpdateException("Failed to processChallenge");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1208,7 +1208,7 @@ public class TestProtocolRecommendations extends AbstractProtocolTest {
|
|||
}
|
||||
|
||||
/* "If the entity-tag of the new response matches that of an existing
|
||||
* entry, the new response SHOULD be used to update the header fields
|
||||
* entry, the new response SHOULD be used to processChallenge the header fields
|
||||
* of the existing entry, and the result MUST be returned to the
|
||||
* client."
|
||||
*
|
||||
|
|
|
@ -2198,8 +2198,8 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
|
|||
}
|
||||
|
||||
/*
|
||||
* "If a cache uses a received 304 response to update a cache entry, the
|
||||
* cache MUST update the entry to reflect any new field values given in the
|
||||
* "If a cache uses a received 304 response to processChallenge a cache entry, the
|
||||
* cache MUST processChallenge the entry to reflect any new field values given in the
|
||||
* response.
|
||||
*
|
||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5
|
||||
|
@ -4539,7 +4539,7 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
|
|||
* the ETag header field in its 304 (Not Modified) response to
|
||||
* tell the cache which entry is appropriate. If the entity-tag of
|
||||
* the new response matches that of an existing entry, the new
|
||||
* response SHOULD be used to update the header fields of the
|
||||
* response SHOULD be used to processChallenge the header fields of the
|
||||
* existing entry, and the result MUST be returned to the client.
|
||||
*
|
||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6
|
||||
|
|
|
@ -168,7 +168,7 @@ public class TestEhcacheHttpCacheStorage extends TestCase {
|
|||
when(mockCache.get(key)).thenReturn(existingElement);
|
||||
when(mockSerializer.readFrom(isA(InputStream.class))).thenReturn(existingValue);
|
||||
|
||||
// update
|
||||
// processChallenge
|
||||
mockSerializer.writeTo(same(updatedValue), isA(OutputStream.class));
|
||||
when(mockCache.replace(same(existingElement), isA(Element.class))).thenReturn(true);
|
||||
|
||||
|
@ -231,7 +231,7 @@ public class TestEhcacheHttpCacheStorage extends TestCase {
|
|||
when(mockCache.get(key)).thenReturn(existingElement);
|
||||
when(mockSerializer.readFrom(isA(InputStream.class))).thenReturn(existingValue);
|
||||
|
||||
// update but fail
|
||||
// processChallenge but fail
|
||||
when(mockCache.replace(same(existingElement), isA(Element.class))).thenReturn(false);
|
||||
|
||||
try{
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.win;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.security.Principal;
|
||||
|
||||
import org.apache.http.annotation.Immutable;
|
||||
import org.apache.http.auth.Credentials;
|
||||
|
||||
import com.sun.jna.platform.win32.Secur32.EXTENDED_NAME_FORMAT;
|
||||
import com.sun.jna.platform.win32.Secur32Util;
|
||||
|
||||
/**
|
||||
* Returns the current Windows user credentials
|
||||
* <p>
|
||||
* EXPERIMENTAL
|
||||
* </p>
|
||||
*
|
||||
* @since 4.4
|
||||
*/
|
||||
@Immutable
|
||||
public final class CurrentWindowsCredentials implements Credentials, Serializable, Principal {
|
||||
|
||||
private static final long serialVersionUID = 4361166468529298169L;
|
||||
|
||||
public static final CurrentWindowsCredentials INSTANCE = new CurrentWindowsCredentials();
|
||||
|
||||
/**
|
||||
* Get the SAM-compatible username of the currently logged-on user.
|
||||
*
|
||||
* @return String.
|
||||
*/
|
||||
public static String getCurrentUsername() {
|
||||
return Secur32Util.getUserNameEx(EXTENDED_NAME_FORMAT.NameSamCompatible);
|
||||
}
|
||||
|
||||
private CurrentWindowsCredentials() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getUserPrincipal() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getClass().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
return getClass().equals(o.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getCurrentUsername();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an empty password
|
||||
*/
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getCurrentUsername();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.win;
|
||||
|
||||
import org.apache.http.annotation.ThreadSafe;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.client.CredentialsStore;
|
||||
import org.apache.http.client.config.AuthSchemes;
|
||||
import org.apache.http.util.Args;
|
||||
|
||||
/**
|
||||
* {@link CredentialsStore} implementation that always returns
|
||||
* {@link org.apache.http.impl.auth.win.CurrentWindowsCredentials} instance to NTLM
|
||||
* and SPNego authentication challenges.
|
||||
* <p>
|
||||
* EXPERIMENTAL
|
||||
* </p>
|
||||
*
|
||||
* @since 4.4
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class WindowsCredentialsProvider implements CredentialsStore {
|
||||
|
||||
private final CredentialsStore provider;
|
||||
|
||||
public WindowsCredentialsProvider(final CredentialsStore provider) {
|
||||
this.provider = Args.notNull(provider, "Credentials provider");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Credentials getCredentials(final AuthScope authscope) {
|
||||
final String scheme = authscope.getScheme();
|
||||
if (AuthSchemes.NTLM.equalsIgnoreCase(scheme) || AuthSchemes.SPNEGO.equalsIgnoreCase(scheme)) {
|
||||
return CurrentWindowsCredentials.INSTANCE;
|
||||
} else {
|
||||
return provider.getCredentials(authscope);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCredentials(final AuthScope authscope, final Credentials credentials) {
|
||||
provider.setCredentials(authscope, credentials);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
provider.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -26,29 +26,28 @@
|
|||
*/
|
||||
package org.apache.http.impl.auth.win;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpHeaders;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.annotation.NotThreadSafe;
|
||||
import org.apache.http.auth.AuthChallenge;
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.AuthenticationException;
|
||||
import org.apache.http.auth.ChallengeType;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.auth.InvalidCredentialsException;
|
||||
import org.apache.http.auth.BasicUserPrincipal;
|
||||
import org.apache.http.auth.CredentialsProvider;
|
||||
import org.apache.http.auth.MalformedChallengeException;
|
||||
import org.apache.http.client.config.AuthSchemes;
|
||||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.conn.routing.RouteInfo;
|
||||
import org.apache.http.impl.auth.NonStandardAuthScheme;
|
||||
import org.apache.http.message.BufferedHeader;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.util.CharArrayBuffer;
|
||||
import org.apache.http.util.Args;
|
||||
|
||||
import com.sun.jna.platform.win32.Secur32;
|
||||
import com.sun.jna.platform.win32.Secur32Util;
|
||||
import com.sun.jna.platform.win32.Sspi;
|
||||
import com.sun.jna.platform.win32.Sspi.CredHandle;
|
||||
import com.sun.jna.platform.win32.Sspi.CtxtHandle;
|
||||
|
@ -70,7 +69,7 @@ import com.sun.jna.ptr.IntByReference;
|
|||
* @since 4.4
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class WindowsNegotiateScheme extends NonStandardAuthScheme {
|
||||
public class WindowsNegotiateScheme implements AuthScheme {
|
||||
|
||||
private final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
|
@ -78,6 +77,7 @@ public class WindowsNegotiateScheme extends NonStandardAuthScheme {
|
|||
private final String scheme;
|
||||
private final String servicePrincipalName;
|
||||
|
||||
private String challenge;
|
||||
private CredHandle clientCred;
|
||||
private CtxtHandle sspiContext;
|
||||
private boolean continueNeeded;
|
||||
|
@ -119,7 +119,7 @@ public class WindowsNegotiateScheme extends NonStandardAuthScheme {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getSchemeName() {
|
||||
public String getName() {
|
||||
return scheme;
|
||||
}
|
||||
|
||||
|
@ -128,11 +128,20 @@ public class WindowsNegotiateScheme extends NonStandardAuthScheme {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRealm() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processChallenge(
|
||||
final ChallengeType challengeType, final AuthChallenge authChallenge) throws MalformedChallengeException {
|
||||
update(challengeType, authChallenge);
|
||||
final String challenge = getChallenge();
|
||||
final AuthChallenge authChallenge,
|
||||
final HttpContext context) throws MalformedChallengeException {
|
||||
Args.notNull(authChallenge, "AuthChallenge");
|
||||
if (authChallenge.getValue() == null) {
|
||||
throw new MalformedChallengeException("Missing auth challenge");
|
||||
}
|
||||
challenge = authChallenge.getValue();
|
||||
if (challenge.isEmpty()) {
|
||||
if (clientCred != null) {
|
||||
dispose(); // run cleanup first before throwing an exception otherwise can leak OS resources
|
||||
|
@ -144,24 +153,38 @@ public class WindowsNegotiateScheme extends NonStandardAuthScheme {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Header authenticate(
|
||||
final Credentials credentials,
|
||||
public boolean isResponseReady(
|
||||
final HttpHost host,
|
||||
final CredentialsProvider credentialsProvider,
|
||||
final HttpContext context) throws AuthenticationException {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SAM-compatible username of the currently logged-on user.
|
||||
*
|
||||
* @return String.
|
||||
*/
|
||||
public static String getCurrentUsername() {
|
||||
return Secur32Util.getUserNameEx(Secur32.EXTENDED_NAME_FORMAT.NameSamCompatible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getPrinciple() {
|
||||
return new BasicUserPrincipal(getCurrentUsername());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateAuthResponse(
|
||||
final HttpHost host,
|
||||
final HttpRequest request,
|
||||
final HttpContext context) throws AuthenticationException {
|
||||
|
||||
final String challenge = getChallenge();
|
||||
final String response;
|
||||
if (clientCred == null) {
|
||||
// ?? We don't use the credentials, should we allow anything?
|
||||
if (!(credentials instanceof CurrentWindowsCredentials)) {
|
||||
throw new InvalidCredentialsException(
|
||||
"Credentials cannot be used for " + getSchemeName() + " authentication: "
|
||||
+ credentials.getClass().getName());
|
||||
}
|
||||
|
||||
// client credentials handle
|
||||
try {
|
||||
final String username = CurrentWindowsCredentials.getCurrentUsername();
|
||||
final String username = getCurrentUsername();
|
||||
final TimeStamp lifetime = new TimeStamp();
|
||||
|
||||
clientCred = new CredHandle();
|
||||
|
@ -202,18 +225,7 @@ public class WindowsNegotiateScheme extends NonStandardAuthScheme {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
final CharArrayBuffer buffer = new CharArrayBuffer(scheme.length() + 30);
|
||||
if (isProxy()) {
|
||||
buffer.append(HttpHeaders.PROXY_AUTHORIZATION);
|
||||
} else {
|
||||
buffer.append(HttpHeaders.AUTHORIZATION);
|
||||
}
|
||||
buffer.append(": ");
|
||||
buffer.append(scheme); // NTLM or Negotiate
|
||||
buffer.append(" ");
|
||||
buffer.append(response);
|
||||
return new BufferedHeader(buffer);
|
||||
return scheme + " " + response;
|
||||
}
|
||||
|
||||
private void failAuthCleanup() {
|
||||
|
@ -281,7 +293,7 @@ public class WindowsNegotiateScheme extends NonStandardAuthScheme {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isComplete() {
|
||||
public boolean isChallengeComplete() {
|
||||
return !continueNeeded;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,13 +29,11 @@ package org.apache.http.impl.client;
|
|||
import java.util.Locale;
|
||||
|
||||
import org.apache.http.auth.AuthSchemeProvider;
|
||||
import org.apache.http.auth.CredentialsProvider;
|
||||
import org.apache.http.client.config.AuthSchemes;
|
||||
import org.apache.http.config.Registry;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.impl.auth.BasicSchemeFactory;
|
||||
import org.apache.http.impl.auth.DigestSchemeFactory;
|
||||
import org.apache.http.impl.auth.win.WindowsCredentialsProvider;
|
||||
import org.apache.http.impl.auth.win.WindowsNTLMSchemeFactory;
|
||||
import org.apache.http.impl.auth.win.WindowsNegotiateSchemeFactory;
|
||||
|
||||
|
@ -74,9 +72,7 @@ public class WinHttpClients {
|
|||
.register(AuthSchemes.NTLM, new WindowsNTLMSchemeFactory(null))
|
||||
.register(AuthSchemes.SPNEGO, new WindowsNegotiateSchemeFactory(null))
|
||||
.build();
|
||||
final CredentialsProvider credsProvider = new WindowsCredentialsProvider(new SystemDefaultCredentialsProvider());
|
||||
return HttpClientBuilder.create()
|
||||
.setDefaultCredentialsProvider(credsProvider)
|
||||
.setDefaultAuthSchemeRegistry(authSchemeRegistry);
|
||||
} else {
|
||||
return HttpClientBuilder.create();
|
||||
|
|
|
@ -36,7 +36,6 @@ import org.apache.http.HttpResponse;
|
|||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.AuthSchemeProvider;
|
||||
import org.apache.http.auth.CredentialsProvider;
|
||||
import org.apache.http.client.config.AuthSchemes;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
|
@ -44,7 +43,6 @@ import org.apache.http.config.Registry;
|
|||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.SystemDefaultCredentialsProvider;
|
||||
import org.apache.http.impl.client.WinHttpClients;
|
||||
import org.apache.http.localserver.LocalServerTestBase;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
|
@ -105,10 +103,7 @@ public class TestWindowsNegotiateScheme extends LocalServerTestBase {
|
|||
return new WindowsNegotiateSchemeGetTokenFail(AuthSchemes.SPNEGO, "HTTP/example.com");
|
||||
}
|
||||
}).build();
|
||||
final CredentialsProvider credsProvider =
|
||||
new WindowsCredentialsProvider(new SystemDefaultCredentialsProvider());
|
||||
final CloseableHttpClient customClient = HttpClientBuilder.create()
|
||||
.setDefaultCredentialsProvider(credsProvider)
|
||||
.setDefaultAuthSchemeRegistry(authSchemeRegistry).build();
|
||||
|
||||
final HttpHost target = start();
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
package org.apache.http.examples.client;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.client.AuthCache;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
|
@ -35,7 +34,6 @@ import org.apache.http.client.methods.HttpGet;
|
|||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.impl.auth.BasicScheme;
|
||||
import org.apache.http.impl.client.BasicAuthCache;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
@ -52,18 +50,13 @@ public class ClientPreemptiveBasicAuthentication {
|
|||
|
||||
public static void main(String[] args) throws Exception {
|
||||
HttpHost target = new HttpHost("localhost", 80, "http");
|
||||
BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
|
||||
credsProvider.setCredentials(
|
||||
new AuthScope(target.getHostName(), target.getPort()),
|
||||
new UsernamePasswordCredentials("username", "password"));
|
||||
try (CloseableHttpClient httpclient = HttpClients.custom()
|
||||
.setDefaultCredentialsProvider(credsProvider).build()) {
|
||||
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
|
||||
|
||||
// Create AuthCache instance
|
||||
AuthCache authCache = new BasicAuthCache();
|
||||
// Generate BASIC scheme object and add it to the local
|
||||
// auth cache
|
||||
// Generate BASIC scheme object and add it to the local auth cache
|
||||
BasicScheme basicAuth = new BasicScheme();
|
||||
basicAuth.initPreemptive(new UsernamePasswordCredentials("username", "password"));
|
||||
authCache.put(target, basicAuth);
|
||||
|
||||
// Add AuthCache to the execution context
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
package org.apache.http.examples.client;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.client.AuthCache;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
|
@ -35,7 +34,6 @@ import org.apache.http.client.methods.HttpGet;
|
|||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.impl.auth.DigestScheme;
|
||||
import org.apache.http.impl.client.BasicAuthCache;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
@ -53,23 +51,14 @@ public class ClientPreemptiveDigestAuthentication {
|
|||
|
||||
public static void main(String[] args) throws Exception {
|
||||
HttpHost target = new HttpHost("localhost", 80, "http");
|
||||
BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
|
||||
credsProvider.setCredentials(
|
||||
new AuthScope(target.getHostName(), target.getPort()),
|
||||
new UsernamePasswordCredentials("username", "password"));
|
||||
try (CloseableHttpClient httpclient = HttpClients.custom()
|
||||
.setDefaultCredentialsProvider(credsProvider)
|
||||
.build()) {
|
||||
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
|
||||
|
||||
// Create AuthCache instance
|
||||
AuthCache authCache = new BasicAuthCache();
|
||||
// Generate DIGEST scheme object, initialize it and add it to the local
|
||||
// auth cache
|
||||
// Generate DIGEST scheme object, initialize it and add it to the local auth cache
|
||||
DigestScheme digestAuth = new DigestScheme();
|
||||
// Suppose we already know the realm name
|
||||
digestAuth.overrideParamter("realm", "some realm");
|
||||
// Suppose we already know the expected nonce value
|
||||
digestAuth.overrideParamter("nonce", "whatever");
|
||||
// Suppose we already know the realm name and the expected nonce value
|
||||
digestAuth.initPreemptive(new UsernamePasswordCredentials("username", "password"), "whatever", "realm");
|
||||
authCache.put(target, digestAuth);
|
||||
|
||||
// Add AuthCache to the execution context
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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;
|
||||
|
||||
import org.apache.http.annotation.Immutable;
|
||||
import org.apache.http.util.Args;
|
||||
|
||||
/**
|
||||
* @since 4.2
|
||||
*/
|
||||
@Immutable
|
||||
public final class AuthOption {
|
||||
|
||||
private final AuthScheme authScheme;
|
||||
private final Credentials creds;
|
||||
|
||||
public AuthOption(final AuthScheme authScheme, final Credentials creds) {
|
||||
super();
|
||||
Args.notNull(authScheme, "Auth scheme");
|
||||
Args.notNull(creds, "User credentials");
|
||||
this.authScheme = authScheme;
|
||||
this.creds = creds;
|
||||
}
|
||||
|
||||
public AuthScheme getAuthScheme() {
|
||||
return this.authScheme;
|
||||
}
|
||||
|
||||
public Credentials getCredentials() {
|
||||
return this.creds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.authScheme.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -26,69 +26,106 @@
|
|||
*/
|
||||
package org.apache.http.auth;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import java.security.Principal;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
|
||||
/**
|
||||
* This interface represents an abstract challenge-response oriented
|
||||
* authentication scheme.
|
||||
* This interface represents an abstract challenge-response oriented authentication scheme.
|
||||
* <p>
|
||||
* Authentication schemes may be stateful involving a series of
|
||||
* challenge-response exchanges.
|
||||
* Authentication schemes can be either request or connection based. The former are
|
||||
* expected to provide an authorization response with each request message while the latter
|
||||
* is executed only once and applies to the underlying connection for its entire life span.
|
||||
* Care must be taken when re-using connections authorized through a connection based
|
||||
* authentication scheme and they may carry a particular security context and be authorized
|
||||
* for a particular user identity. It is important that such schemes always provide
|
||||
* the user identity they represent through the {@link #getPrinciple()} method.
|
||||
* <p>
|
||||
* Authentication scheme are expected to transition through a series of standard phases or
|
||||
* states.
|
||||
* <p>
|
||||
* Authentication scheme starts off its life cycle with no context and no specific state.
|
||||
* <p>
|
||||
* The {@link #processChallenge(AuthChallenge, HttpContext)} method is called to
|
||||
* process an authentication challenge received either from the target server or a proxy.
|
||||
* The authentication scheme transitions to CHALLENGED state and is expected to validate
|
||||
* the token passed to it as a parameter and initialize its internal state based on
|
||||
* challenge details. Standard authentication schemes are expected to provide a realm
|
||||
* attribute in the challenge. {@link #getRealm()} can be called to obtain an identifier
|
||||
* of the realm that requires authorization.
|
||||
* <p>
|
||||
* Once the challenge has been fully processed the {@link #isResponseReady(HttpHost,
|
||||
* CredentialsProvider, HttpContext)} method to determine whether the scheme is capable of
|
||||
* generating a authorization response based on its current state and it holds user credentials
|
||||
* required to do so. If this method returns {@code false} the authentication is considered
|
||||
* to be in FAILED state and no authorization response. Otherwise the scheme is considered
|
||||
* to be in RESPONSE_READY state.
|
||||
* <p>
|
||||
* Once the scheme is ready to respond to the challenge the {@link #generateAuthResponse(
|
||||
* HttpHost, HttpRequest, HttpContext)} method to generate a response token, which will
|
||||
* be sent to the opposite endpoint in the subsequent request message.
|
||||
* <p>
|
||||
* Certain non-standard schemes may involve multiple challenge / response exchanges to
|
||||
* fully establish a shared context and complete the authentication process. Authentication
|
||||
* schemes are required to return {@code true} {@link #isChallengeComplete()} once the
|
||||
* handshake is considered complete.
|
||||
* <p>
|
||||
* The authentication scheme is considered successfully completed and in SUCCESS state
|
||||
* if the opposite endpoint accepts the request message containing the authorization
|
||||
* response and responds with a message indicating no authentication failure .
|
||||
* If the opposite endpoint sends status code 401 or 407 in response to a request message
|
||||
* containing the terminal authorization response, the scheme is considered unsuccessful
|
||||
* and in FAILED state.
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
|
||||
public interface AuthScheme {
|
||||
|
||||
/**
|
||||
* 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 challengeType the challenge type
|
||||
* @param authChallenge the auth challenge
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
void processChallenge(
|
||||
ChallengeType challengeType,
|
||||
AuthChallenge authChallenge) throws MalformedChallengeException;
|
||||
|
||||
/**
|
||||
* Produces an authorization string for the given set of {@link Credentials}.
|
||||
*
|
||||
* @param credentials The credentials to be used for authentication
|
||||
* @param request The request being authenticated
|
||||
* @param context HTTP context
|
||||
* @throws AuthenticationException if authorization string cannot
|
||||
* be generated due to an authentication failure
|
||||
*
|
||||
* @return authorization header
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
Header authenticate(
|
||||
Credentials credentials,
|
||||
HttpRequest request,
|
||||
HttpContext context) throws AuthenticationException;
|
||||
|
||||
/**
|
||||
* Returns textual designation of the given authentication scheme.
|
||||
*
|
||||
* @return the name of the given authentication scheme
|
||||
*/
|
||||
String getSchemeName();
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Returns authentication parameter with the given name, if available.
|
||||
* Determines if the authentication scheme is expected to provide an authorization response
|
||||
* on a per connection basis instead of the standard per request basis
|
||||
*
|
||||
* @param name The name of the parameter to be returned
|
||||
*
|
||||
* @return the parameter with the given name
|
||||
* @return {@code true} if the scheme is connection based, {@code false}
|
||||
* if the scheme is request based.
|
||||
*/
|
||||
String getParameter(final String name);
|
||||
boolean isConnectionBased();
|
||||
|
||||
/**
|
||||
* Processes the given auth challenge. Some authentication schemes may involve multiple
|
||||
* challenge-response exchanges. Such schemes must be able to maintain internal state
|
||||
* when dealing with sequential challenges
|
||||
*
|
||||
* @param authChallenge the auth challenge
|
||||
* @param context HTTP context
|
||||
* @throws MalformedChallengeException in case the auth challenge is incomplete,
|
||||
* malformed or otherwise invalid.
|
||||
* @since 5.0
|
||||
*/
|
||||
void processChallenge(
|
||||
AuthChallenge authChallenge,
|
||||
HttpContext context) throws MalformedChallengeException;
|
||||
|
||||
/**
|
||||
* Authentication process may involve a series of challenge-response exchanges.
|
||||
* This method tests if the authorization process has been fully completed (either
|
||||
* successfully or unsuccessfully), that is, all the required authorization
|
||||
* challenges have been processed in their entirety.
|
||||
*
|
||||
* @return {@code true} if the authentication process has been completed,
|
||||
* {@code false} otherwise.
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
boolean isChallengeComplete();
|
||||
|
||||
/**
|
||||
* Returns authentication realm. If the concept of an authentication
|
||||
|
@ -100,23 +137,58 @@ public interface AuthScheme {
|
|||
String getRealm();
|
||||
|
||||
/**
|
||||
* Tests if the authentication scheme is provides authorization on a per
|
||||
* connection basis instead of usual per request basis
|
||||
* Determines whether or not an authorization response can be generated based on
|
||||
* the actual authentication state. Generally the outcome of this method will depend
|
||||
* upon availability of user credentials necessary to produce an authorization
|
||||
* response.
|
||||
*
|
||||
* @return {@code true} if the scheme is connection based, {@code false}
|
||||
* if the scheme is request based.
|
||||
* @param credentialsProvider The credentials to be used for authentication
|
||||
* @param context HTTP context
|
||||
* @throws AuthenticationException if authorization string cannot
|
||||
* be generated due to an authentication failure
|
||||
*
|
||||
* @return {@code true} if an authorization response can be generated and
|
||||
* the authentication handshake can proceed, {@code false} otherwise.
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
boolean isConnectionBased();
|
||||
boolean isResponseReady(
|
||||
HttpHost host,
|
||||
CredentialsProvider credentialsProvider,
|
||||
HttpContext context) throws AuthenticationException;
|
||||
|
||||
/**
|
||||
* Authentication process may involve a series of challenge-response exchanges.
|
||||
* This method tests if the authorization process has been completed, either
|
||||
* successfully or unsuccessfully, that is, all the required authorization
|
||||
* challenges have been processed in their entirety.
|
||||
* Returns {@link Principal} whose credentials are used to generate
|
||||
* an authentication response. Connection based schemes are required
|
||||
* to return a user {@link Principal} if authorization applies to
|
||||
* for the entire life span of connection.
|
||||
* @return user principle
|
||||
*
|
||||
* @return {@code true} if the authentication process has been completed,
|
||||
* {@code false} otherwise.
|
||||
* @see #isConnectionBased()
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
boolean isComplete();
|
||||
Principal getPrinciple();
|
||||
|
||||
/**
|
||||
* Generates an authorization response based on the current state. Some authentication
|
||||
* schemes may need to load user credentials required to generate an authorization
|
||||
* response from a {@link CredentialsProvider} prior to this method call.
|
||||
*
|
||||
* @param request The request being authenticated
|
||||
* @param context HTTP context
|
||||
* @throws AuthenticationException if authorization string cannot
|
||||
* be generated due to an authentication failure
|
||||
*
|
||||
* @return authorization header
|
||||
*
|
||||
* @see #isResponseReady(HttpHost, CredentialsProvider, HttpContext)
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
String generateAuthResponse(
|
||||
HttpHost host,
|
||||
HttpRequest request,
|
||||
HttpContext context) throws AuthenticationException;
|
||||
|
||||
}
|
||||
|
|
|
@ -45,11 +45,8 @@ public class AuthState {
|
|||
/** Actual authentication scheme */
|
||||
private AuthScheme authScheme;
|
||||
|
||||
/** Credentials selected for authentication */
|
||||
private Credentials credentials;
|
||||
|
||||
/** Available auth options */
|
||||
private Queue<AuthOption> authOptions;
|
||||
private Queue<AuthScheme> authOptions;
|
||||
|
||||
public AuthState() {
|
||||
super();
|
||||
|
@ -65,7 +62,6 @@ public class AuthState {
|
|||
this.state = AuthProtocolState.UNCHALLENGED;
|
||||
this.authOptions = null;
|
||||
this.authScheme = null;
|
||||
this.credentials = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -90,71 +86,48 @@ public class AuthState {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns actual {@link Credentials}. May be null.
|
||||
*/
|
||||
public Credentials getCredentials() {
|
||||
return this.credentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the auth state with {@link AuthScheme} and {@link Credentials}.
|
||||
* Updates the auth state with {@link AuthScheme} and clears auth options.
|
||||
*
|
||||
* @param authScheme auth scheme. May not be null.
|
||||
* @param credentials user crednetials. May not be null.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public void update(final AuthScheme authScheme, final Credentials credentials) {
|
||||
public void update(final AuthScheme authScheme) {
|
||||
Args.notNull(authScheme, "Auth scheme");
|
||||
Args.notNull(credentials, "Credentials");
|
||||
this.authScheme = authScheme;
|
||||
this.credentials = credentials;
|
||||
this.authOptions = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns available {@link AuthOption}s. May be null.
|
||||
* Returns available auth options. May be null.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public Queue<AuthOption> getAuthOptions() {
|
||||
public Queue<AuthScheme> getAuthOptions() {
|
||||
return this.authOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if {@link AuthOption}s are available, {@code false}
|
||||
* otherwise.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public boolean hasAuthOptions() {
|
||||
return this.authOptions != null && !this.authOptions.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the auth state with a queue of {@link AuthOption}s.
|
||||
* Updates the auth state with a queue of auth options.
|
||||
*
|
||||
* @param authOptions a queue of auth options. May not be null or empty.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public void update(final Queue<AuthOption> authOptions) {
|
||||
public void update(final Queue<AuthScheme> authOptions) {
|
||||
Args.notEmpty(authOptions, "Queue of auth options");
|
||||
this.authOptions = authOptions;
|
||||
this.authScheme = null;
|
||||
this.credentials = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder buffer = new StringBuilder();
|
||||
buffer.append("state:").append(this.state).append(";");
|
||||
buffer.append("[").append(this.state);
|
||||
if (this.authScheme != null) {
|
||||
buffer.append("auth scheme:").append(this.authScheme.getSchemeName()).append(";");
|
||||
}
|
||||
if (this.credentials != null) {
|
||||
buffer.append("credentials present");
|
||||
buffer.append(" ").append(this.authScheme);
|
||||
}
|
||||
buffer.append("]");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
|
|
|
@ -38,9 +38,7 @@ import org.apache.http.HttpRequestInterceptor;
|
|||
import org.apache.http.annotation.Immutable;
|
||||
import org.apache.http.auth.AuthProtocolState;
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.AuthState;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.auth.CredentialsProvider;
|
||||
import org.apache.http.client.AuthCache;
|
||||
import org.apache.http.conn.routing.RouteInfo;
|
||||
|
@ -106,7 +104,10 @@ public class RequestAuthCache implements HttpRequestInterceptor {
|
|||
if (targetState != null && targetState.getState() == AuthProtocolState.UNCHALLENGED) {
|
||||
final AuthScheme authScheme = authCache.get(target);
|
||||
if (authScheme != null) {
|
||||
doPreemptiveAuth(target, authScheme, targetState, credsProvider);
|
||||
if (this.log.isDebugEnabled()) {
|
||||
this.log.debug("Re-using cached '" + authScheme.getName() + "' auth scheme for " + target);
|
||||
}
|
||||
targetState.update(authScheme);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,34 +116,12 @@ public class RequestAuthCache implements HttpRequestInterceptor {
|
|||
if (proxy != null && proxyState != null && proxyState.getState() == AuthProtocolState.UNCHALLENGED) {
|
||||
final AuthScheme authScheme = authCache.get(proxy);
|
||||
if (authScheme != null) {
|
||||
doPreemptiveAuth(proxy, authScheme, proxyState, credsProvider);
|
||||
if (this.log.isDebugEnabled()) {
|
||||
this.log.debug("Re-using cached '" + authScheme.getName() + "' auth scheme for " + proxy);
|
||||
}
|
||||
proxyState.update(authScheme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doPreemptiveAuth(
|
||||
final HttpHost host,
|
||||
final AuthScheme authScheme,
|
||||
final AuthState authState,
|
||||
final CredentialsProvider credsProvider) {
|
||||
final String schemeName = authScheme.getSchemeName();
|
||||
if (this.log.isDebugEnabled()) {
|
||||
this.log.debug("Re-using cached '" + schemeName + "' auth scheme for " + host);
|
||||
}
|
||||
|
||||
final AuthScope authScope = new AuthScope(host, AuthScope.ANY_REALM, schemeName);
|
||||
final Credentials creds = credsProvider.getCredentials(authScope);
|
||||
|
||||
if (creds != null) {
|
||||
if ("BASIC".equalsIgnoreCase(authScheme.getSchemeName())) {
|
||||
authState.setState(AuthProtocolState.CHALLENGED);
|
||||
} else {
|
||||
authState.setState(AuthProtocolState.SUCCESS);
|
||||
}
|
||||
authState.update(authScheme, creds);
|
||||
} else {
|
||||
this.log.debug("No credentials for preemptive authentication");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ package org.apache.http.cookie;
|
|||
public interface CookieAttributeHandler {
|
||||
|
||||
/**
|
||||
* Parse the given cookie attribute value and update the corresponding
|
||||
* Parse the given cookie attribute value and processChallenge the corresponding
|
||||
* {@link org.apache.http.cookie.Cookie} property.
|
||||
*
|
||||
* @param cookie {@link org.apache.http.cookie.Cookie} to be updated
|
||||
|
|
|
@ -54,7 +54,7 @@ public class CookiePriorityComparator implements Comparator<Cookie> {
|
|||
public int compare(final Cookie c1, final Cookie c2) {
|
||||
final int l1 = getPathLength(c1);
|
||||
final int l2 = getPathLength(c2);
|
||||
//TODO: update this class once Cookie interface has been expended with #getCreationTime method
|
||||
//TODO: processChallenge this class once Cookie interface has been expended with #getCreationTime method
|
||||
final int result = l2 - l1;
|
||||
if (result == 0 && c1 instanceof BasicClientCookie && c2 instanceof BasicClientCookie) {
|
||||
final Date d1 = ((BasicClientCookie) c1).getCreationDate();
|
||||
|
|
|
@ -30,23 +30,29 @@ import java.io.IOException;
|
|||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.Principal;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpHeaders;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.annotation.NotThreadSafe;
|
||||
import org.apache.http.auth.AuthChallenge;
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.AuthenticationException;
|
||||
import org.apache.http.auth.ChallengeType;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.auth.CredentialsProvider;
|
||||
import org.apache.http.auth.MalformedChallengeException;
|
||||
import org.apache.http.message.BufferedHeader;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.util.Args;
|
||||
import org.apache.http.util.CharArrayBuffer;
|
||||
import org.apache.http.util.CharsetUtils;
|
||||
import org.apache.http.util.EncodingUtils;
|
||||
|
||||
|
@ -56,17 +62,21 @@ import org.apache.http.util.EncodingUtils;
|
|||
* @since 4.0
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class BasicScheme extends StandardAuthScheme {
|
||||
public class BasicScheme implements AuthScheme, Serializable {
|
||||
|
||||
private static final long serialVersionUID = -1931571557597830536L;
|
||||
|
||||
private final Map<String, String> paramMap;
|
||||
private transient Charset charset;
|
||||
private boolean complete;
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* @since 4.3
|
||||
*/
|
||||
public BasicScheme(final Charset charset) {
|
||||
this.paramMap = new HashMap<>();
|
||||
this.charset = charset != null ? charset : Consts.ASCII;
|
||||
this.complete = false;
|
||||
}
|
||||
|
@ -75,54 +85,88 @@ public class BasicScheme extends StandardAuthScheme {
|
|||
this(Consts.ASCII);
|
||||
}
|
||||
|
||||
public void initPreemptive(final Credentials credentials) {
|
||||
if (credentials != null) {
|
||||
this.username = credentials.getUserPrincipal().getName();
|
||||
this.password = credentials.getPassword();
|
||||
} else {
|
||||
this.username = null;
|
||||
this.password = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchemeName() {
|
||||
public String getName() {
|
||||
return "basic";
|
||||
}
|
||||
|
||||
public void processChallenge(
|
||||
final ChallengeType challengeType,
|
||||
final AuthChallenge authChallenge) throws MalformedChallengeException {
|
||||
update(challengeType, authChallenge);
|
||||
this.complete = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isComplete() {
|
||||
return this.complete;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnectionBased() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Header authenticate(
|
||||
final Credentials credentials,
|
||||
final HttpRequest request,
|
||||
public String getRealm() {
|
||||
return this.paramMap.get("realm");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processChallenge(
|
||||
final AuthChallenge authChallenge,
|
||||
final HttpContext context) throws MalformedChallengeException {
|
||||
this.paramMap.clear();
|
||||
final List<NameValuePair> params = authChallenge.getParams();
|
||||
if (params != null) {
|
||||
for (NameValuePair param: params) {
|
||||
this.paramMap.put(param.getName().toLowerCase(Locale.ROOT), param.getValue());
|
||||
}
|
||||
}
|
||||
this.complete = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChallengeComplete() {
|
||||
return this.complete;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResponseReady(
|
||||
final HttpHost host,
|
||||
final CredentialsProvider credentialsProvider,
|
||||
final HttpContext context) throws AuthenticationException {
|
||||
|
||||
Args.notNull(credentials, "Credentials");
|
||||
Args.notNull(request, "HTTP request");
|
||||
final CharArrayBuffer buffer = new CharArrayBuffer(32);
|
||||
if (isProxy()) {
|
||||
buffer.append(HttpHeaders.PROXY_AUTHORIZATION);
|
||||
Args.notNull(host, "Auth host");
|
||||
Args.notNull(credentialsProvider, "CredentialsProvider");
|
||||
|
||||
final Credentials credentials = credentialsProvider.getCredentials(new AuthScope(host, getRealm(), getName()));
|
||||
if (credentials != null) {
|
||||
this.username = credentials.getUserPrincipal().getName();
|
||||
this.password = credentials.getPassword();
|
||||
return true;
|
||||
} else {
|
||||
buffer.append(HttpHeaders.AUTHORIZATION);
|
||||
this.username = null;
|
||||
this.password = null;
|
||||
return false;
|
||||
}
|
||||
buffer.append(": Basic ");
|
||||
}
|
||||
|
||||
final StringBuilder tmp = new StringBuilder();
|
||||
tmp.append(credentials.getUserPrincipal().getName());
|
||||
tmp.append(":");
|
||||
tmp.append((credentials.getPassword() == null) ? "null" : credentials.getPassword());
|
||||
@Override
|
||||
public Principal getPrinciple() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateAuthResponse(
|
||||
final HttpHost host,
|
||||
final HttpRequest request,
|
||||
final HttpContext context) throws AuthenticationException {
|
||||
final StringBuilder buffer = new StringBuilder();
|
||||
buffer.append(this.username);
|
||||
buffer.append(":");
|
||||
buffer.append(this.password);
|
||||
final Base64 base64codec = new Base64(0);
|
||||
final byte[] base64password = base64codec.encode(EncodingUtils.getBytes(tmp.toString(), charset.name()));
|
||||
|
||||
buffer.append(base64password, 0, base64password.length);
|
||||
return new BufferedHeader(buffer);
|
||||
final byte[] encodedCreds = base64codec.encode(EncodingUtils.getBytes(buffer.toString(), charset.name()));
|
||||
return "Basic " + new String(encodedCreds, 0, encodedCreds.length, Consts.ASCII);
|
||||
}
|
||||
|
||||
private void writeObject(final ObjectOutputStream out) throws IOException {
|
||||
|
@ -142,4 +186,9 @@ public class BasicScheme extends StandardAuthScheme {
|
|||
private void readObjectNoData() throws ObjectStreamException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.paramMap.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,30 +27,35 @@
|
|||
package org.apache.http.impl.auth;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.Principal;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Formatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpEntityEnclosingRequest;
|
||||
import org.apache.http.HttpHeaders;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.annotation.NotThreadSafe;
|
||||
import org.apache.http.auth.AuthChallenge;
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.AuthenticationException;
|
||||
import org.apache.http.auth.ChallengeType;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.auth.CredentialsProvider;
|
||||
import org.apache.http.auth.MalformedChallengeException;
|
||||
import org.apache.http.message.BasicHeaderValueFormatter;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.apache.http.message.BufferedHeader;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.util.Args;
|
||||
import org.apache.http.util.CharArrayBuffer;
|
||||
|
@ -71,7 +76,7 @@ import org.apache.http.util.EncodingUtils;
|
|||
* @since 4.0
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class DigestScheme extends StandardAuthScheme {
|
||||
public class DigestScheme implements AuthScheme, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 3883908186234566916L;
|
||||
|
||||
|
@ -86,49 +91,37 @@ public class DigestScheme extends StandardAuthScheme {
|
|||
'e', 'f'
|
||||
};
|
||||
|
||||
/** Whether the digest authentication process is complete */
|
||||
private boolean complete;
|
||||
|
||||
private static final int QOP_UNKNOWN = -1;
|
||||
private static final int QOP_MISSING = 0;
|
||||
private static final int QOP_AUTH_INT = 1;
|
||||
private static final int QOP_AUTH = 2;
|
||||
|
||||
private final Map<String, String> paramMap;
|
||||
private boolean complete;
|
||||
private String lastNonce;
|
||||
private long nounceCount;
|
||||
private String cnonce;
|
||||
private String a1;
|
||||
private String a2;
|
||||
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
public DigestScheme() {
|
||||
this.paramMap = new HashMap<>();
|
||||
this.complete = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processChallenge(
|
||||
final ChallengeType challengeType,
|
||||
final AuthChallenge authChallenge) throws MalformedChallengeException {
|
||||
Args.notNull(challengeType, "ChallengeType");
|
||||
Args.notNull(authChallenge, "AuthChallenge");
|
||||
update(challengeType, authChallenge);
|
||||
if (getParameters().isEmpty()) {
|
||||
throw new MalformedChallengeException("Missing digest auth parameters");
|
||||
}
|
||||
this.complete = true;
|
||||
public void initPreemptive(final Credentials credentials, final String cnonce, final String realm) {
|
||||
Args.notNull(credentials, "Credentials");
|
||||
this.username = credentials.getUserPrincipal().getName();
|
||||
this.password = credentials.getPassword();
|
||||
this.paramMap.put("cnonce", cnonce);
|
||||
this.paramMap.put("realm", realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isComplete() {
|
||||
final String s = getParameter("stale");
|
||||
if ("true".equalsIgnoreCase(s)) {
|
||||
return false;
|
||||
} else {
|
||||
return this.complete;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchemeName() {
|
||||
public String getName() {
|
||||
return "digest";
|
||||
}
|
||||
|
||||
|
@ -137,28 +130,79 @@ public class DigestScheme extends StandardAuthScheme {
|
|||
return false;
|
||||
}
|
||||
|
||||
public void overrideParamter(final String name, final String value) {
|
||||
getParameters().put(name, value);
|
||||
@Override
|
||||
public String getRealm() {
|
||||
return this.paramMap.get("realm");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Header authenticate(
|
||||
final Credentials credentials,
|
||||
public void processChallenge(
|
||||
final AuthChallenge authChallenge,
|
||||
final HttpContext context) throws MalformedChallengeException {
|
||||
Args.notNull(authChallenge, "AuthChallenge");
|
||||
this.paramMap.clear();
|
||||
final List<NameValuePair> params = authChallenge.getParams();
|
||||
if (params != null) {
|
||||
for (NameValuePair param: params) {
|
||||
this.paramMap.put(param.getName().toLowerCase(Locale.ROOT), param.getValue());
|
||||
}
|
||||
}
|
||||
if (this.paramMap.isEmpty()) {
|
||||
throw new MalformedChallengeException("Missing digest auth parameters");
|
||||
}
|
||||
this.complete = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChallengeComplete() {
|
||||
final String s = this.paramMap.get("stale");
|
||||
if ("true".equalsIgnoreCase(s)) {
|
||||
return false;
|
||||
} else {
|
||||
return this.complete;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResponseReady(
|
||||
final HttpHost host,
|
||||
final CredentialsProvider credentialsProvider,
|
||||
final HttpContext context) throws AuthenticationException {
|
||||
|
||||
Args.notNull(host, "Auth host");
|
||||
Args.notNull(credentialsProvider, "CredentialsProvider");
|
||||
|
||||
final Credentials credentials = credentialsProvider.getCredentials(new AuthScope(host, getRealm(), getName()));
|
||||
if (credentials != null) {
|
||||
this.username = credentials.getUserPrincipal().getName();
|
||||
this.password = credentials.getPassword();
|
||||
return true;
|
||||
} else {
|
||||
this.username = null;
|
||||
this.password = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getPrinciple() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateAuthResponse(
|
||||
final HttpHost host,
|
||||
final HttpRequest request,
|
||||
final HttpContext context) throws AuthenticationException {
|
||||
|
||||
Args.notNull(credentials, "Credentials");
|
||||
Args.notNull(request, "HTTP request");
|
||||
if (getParameter("realm") == null) {
|
||||
throw new AuthenticationException("missing realm in challenge");
|
||||
if (this.paramMap.get("realm") == null) {
|
||||
throw new AuthenticationException("missing realm");
|
||||
}
|
||||
if (getParameter("nonce") == null) {
|
||||
throw new AuthenticationException("missing nonce in challenge");
|
||||
if (this.paramMap.get("nonce") == null) {
|
||||
throw new AuthenticationException("missing nonce");
|
||||
}
|
||||
// Add method name and request-URI to the parameter map
|
||||
getParameters().put("methodname", request.getRequestLine().getMethod());
|
||||
getParameters().put("uri", request.getRequestLine().getUri());
|
||||
return createDigestHeader(credentials, request);
|
||||
return createDigestResponse(request);
|
||||
}
|
||||
|
||||
private static MessageDigest createMessageDigest(
|
||||
|
@ -172,15 +216,14 @@ public class DigestScheme extends StandardAuthScheme {
|
|||
}
|
||||
}
|
||||
|
||||
private Header createDigestHeader(
|
||||
final Credentials credentials,
|
||||
final HttpRequest request) throws AuthenticationException {
|
||||
final String uri = getParameter("uri");
|
||||
final String realm = getParameter("realm");
|
||||
final String nonce = getParameter("nonce");
|
||||
final String opaque = getParameter("opaque");
|
||||
final String method = getParameter("methodname");
|
||||
String algorithm = getParameter("algorithm");
|
||||
private String createDigestResponse(final HttpRequest request) throws AuthenticationException {
|
||||
|
||||
final String uri = request.getRequestLine().getUri();
|
||||
final String method = request.getRequestLine().getMethod();
|
||||
final String realm = this.paramMap.get("realm");
|
||||
final String nonce = this.paramMap.get("nonce");
|
||||
final String opaque = this.paramMap.get("opaque");
|
||||
String algorithm = this.paramMap.get("algorithm");
|
||||
// If an algorithm is not specified, default to MD5.
|
||||
if (algorithm == null) {
|
||||
algorithm = "MD5";
|
||||
|
@ -188,7 +231,7 @@ public class DigestScheme extends StandardAuthScheme {
|
|||
|
||||
final Set<String> qopset = new HashSet<>(8);
|
||||
int qop = QOP_UNKNOWN;
|
||||
final String qoplist = getParameter("qop");
|
||||
final String qoplist = this.paramMap.get("qop");
|
||||
if (qoplist != null) {
|
||||
final StringTokenizer tok = new StringTokenizer(qoplist, ",");
|
||||
while (tok.hasMoreTokens()) {
|
||||
|
@ -208,7 +251,7 @@ public class DigestScheme extends StandardAuthScheme {
|
|||
throw new AuthenticationException("None of the qop methods is supported: " + qoplist);
|
||||
}
|
||||
|
||||
String charset = getParameter("charset");
|
||||
String charset = this.paramMap.get("charset");
|
||||
if (charset == null) {
|
||||
charset = "ISO-8859-1";
|
||||
}
|
||||
|
@ -225,9 +268,6 @@ public class DigestScheme extends StandardAuthScheme {
|
|||
throw new AuthenticationException("Unsuppported digest algorithm: " + digAlg);
|
||||
}
|
||||
|
||||
final String uname = credentials.getUserPrincipal().getName();
|
||||
final String pwd = credentials.getPassword();
|
||||
|
||||
if (nonce.equals(this.lastNonce)) {
|
||||
nounceCount++;
|
||||
} else {
|
||||
|
@ -255,7 +295,7 @@ public class DigestScheme extends StandardAuthScheme {
|
|||
|
||||
// calculated one per session
|
||||
sb.setLength(0);
|
||||
sb.append(uname).append(':').append(realm).append(':').append(pwd);
|
||||
sb.append(username).append(':').append(realm).append(':').append(password);
|
||||
final String checksum = encode(digester.digest(EncodingUtils.getBytes(sb.toString(), charset)));
|
||||
sb.setLength(0);
|
||||
sb.append(checksum).append(':').append(nonce).append(':').append(cnonce);
|
||||
|
@ -263,7 +303,7 @@ public class DigestScheme extends StandardAuthScheme {
|
|||
} else {
|
||||
// unq(username-value) ":" unq(realm-value) ":" passwd
|
||||
sb.setLength(0);
|
||||
sb.append(uname).append(':').append(realm).append(':').append(pwd);
|
||||
sb.append(username).append(':').append(realm).append(':').append(password);
|
||||
a1 = sb.toString();
|
||||
}
|
||||
|
||||
|
@ -323,15 +363,10 @@ public class DigestScheme extends StandardAuthScheme {
|
|||
final String digest = encode(digester.digest(EncodingUtils.getAsciiBytes(digestValue)));
|
||||
|
||||
final CharArrayBuffer buffer = new CharArrayBuffer(128);
|
||||
if (isProxy()) {
|
||||
buffer.append(HttpHeaders.PROXY_AUTHORIZATION);
|
||||
} else {
|
||||
buffer.append(HttpHeaders.AUTHORIZATION);
|
||||
}
|
||||
buffer.append(": Digest ");
|
||||
buffer.append("Digest ");
|
||||
|
||||
final List<BasicNameValuePair> params = new ArrayList<>(20);
|
||||
params.add(new BasicNameValuePair("username", uname));
|
||||
params.add(new BasicNameValuePair("username", username));
|
||||
params.add(new BasicNameValuePair("realm", realm));
|
||||
params.add(new BasicNameValuePair("nonce", nonce));
|
||||
params.add(new BasicNameValuePair("uri", uri));
|
||||
|
@ -358,7 +393,7 @@ public class DigestScheme extends StandardAuthScheme {
|
|||
|| "algorithm".equals(name));
|
||||
BasicHeaderValueFormatter.INSTANCE.formatNameValuePair(buffer, param, !noQuotes);
|
||||
}
|
||||
return new BufferedHeader(buffer);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
String getCnonce() {
|
||||
|
@ -405,4 +440,9 @@ public class DigestScheme extends StandardAuthScheme {
|
|||
return encode(tmp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.paramMap.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,28 +28,25 @@ package org.apache.http.impl.auth;
|
|||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.Principal;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpHeaders;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.annotation.NotThreadSafe;
|
||||
import org.apache.http.auth.AuthChallenge;
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.AuthenticationException;
|
||||
import org.apache.http.auth.ChallengeType;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.auth.CredentialsProvider;
|
||||
import org.apache.http.auth.InvalidCredentialsException;
|
||||
import org.apache.http.auth.KerberosCredentials;
|
||||
import org.apache.http.auth.MalformedChallengeException;
|
||||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.conn.routing.HttpRoute;
|
||||
import org.apache.http.message.BufferedHeader;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.util.Args;
|
||||
import org.apache.http.util.CharArrayBuffer;
|
||||
import org.ietf.jgss.GSSContext;
|
||||
import org.ietf.jgss.GSSCredential;
|
||||
import org.ietf.jgss.GSSException;
|
||||
|
@ -61,7 +58,7 @@ import org.ietf.jgss.Oid;
|
|||
* @since 4.2
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public abstract class GGSSchemeBase extends NonStandardAuthScheme {
|
||||
public abstract class GGSSchemeBase implements AuthScheme {
|
||||
|
||||
enum State {
|
||||
UNINITIATED,
|
||||
|
@ -77,8 +74,8 @@ public abstract class GGSSchemeBase extends NonStandardAuthScheme {
|
|||
|
||||
/** Authentication process state */
|
||||
private State state;
|
||||
|
||||
/** base64 decoded challenge **/
|
||||
private GSSCredential gssCredential;
|
||||
private String challenge;
|
||||
private byte[] token;
|
||||
|
||||
GGSSchemeBase(final boolean stripPort, final boolean useCanonicalHostname) {
|
||||
|
@ -93,19 +90,25 @@ public abstract class GGSSchemeBase extends NonStandardAuthScheme {
|
|||
}
|
||||
|
||||
GGSSchemeBase() {
|
||||
this(true,true);
|
||||
this(true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRealm() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processChallenge(
|
||||
final ChallengeType challengeType,
|
||||
final AuthChallenge authChallenge) throws MalformedChallengeException {
|
||||
update(challengeType, authChallenge);
|
||||
final AuthChallenge authChallenge,
|
||||
final HttpContext context) throws MalformedChallengeException {
|
||||
Args.notNull(authChallenge, "AuthChallenge");
|
||||
if (authChallenge.getValue() == null) {
|
||||
throw new MalformedChallengeException("Missing auth challenge");
|
||||
}
|
||||
this.challenge = authChallenge.getValue();
|
||||
if (state == State.UNINITIATED) {
|
||||
final String challenge = getChallenge();
|
||||
token = Base64.decodeBase64(challenge.getBytes());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Received token '" + token + "' from the auth server");
|
||||
}
|
||||
state = State.CHALLENGE_RECEIVED;
|
||||
} else {
|
||||
log.debug("Authentication already attempted");
|
||||
|
@ -117,17 +120,10 @@ public abstract class GGSSchemeBase extends NonStandardAuthScheme {
|
|||
return GSSManager.getInstance();
|
||||
}
|
||||
|
||||
protected byte[] generateGSSToken(
|
||||
final byte[] input, final Oid oid, final String authServer) throws GSSException {
|
||||
return generateGSSToken(input, oid, authServer, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.4
|
||||
*/
|
||||
protected byte[] generateGSSToken(
|
||||
final byte[] input, final Oid oid, final String authServer,
|
||||
final Credentials credentials) throws GSSException {
|
||||
protected byte[] generateGSSToken(final byte[] input, final Oid oid, final String authServer) throws GSSException {
|
||||
byte[] inputBuff = input;
|
||||
if (inputBuff == null) {
|
||||
inputBuff = new byte[0];
|
||||
|
@ -135,13 +131,6 @@ public abstract class GGSSchemeBase extends NonStandardAuthScheme {
|
|||
final GSSManager manager = getManager();
|
||||
final GSSName serverName = manager.createName("HTTP@" + authServer, GSSName.NT_HOSTBASED_SERVICE);
|
||||
|
||||
final GSSCredential gssCredential;
|
||||
if (credentials instanceof KerberosCredentials) {
|
||||
gssCredential = ((KerberosCredentials) credentials).getGSSCredential();
|
||||
} else {
|
||||
gssCredential = null;
|
||||
}
|
||||
|
||||
final GSSContext gssContext = manager.createContext(
|
||||
serverName.canonicalize(oid), oid, gssCredential, GSSContext.DEFAULT_LIFETIME);
|
||||
gssContext.requestMutualAuth(true);
|
||||
|
@ -152,43 +141,52 @@ public abstract class GGSSchemeBase extends NonStandardAuthScheme {
|
|||
/**
|
||||
* @since 4.4
|
||||
*/
|
||||
protected abstract byte[] generateToken(
|
||||
byte[] input, String authServer, Credentials credentials) throws GSSException;
|
||||
protected abstract byte[] generateToken(byte[] input, String authServer) throws GSSException;
|
||||
|
||||
@Override
|
||||
public boolean isComplete() {
|
||||
public boolean isChallengeComplete() {
|
||||
return this.state == State.TOKEN_GENERATED || this.state == State.FAILED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Header authenticate(
|
||||
final Credentials credentials,
|
||||
public boolean isResponseReady(
|
||||
final HttpHost host,
|
||||
final CredentialsProvider credentialsProvider,
|
||||
final HttpContext context) throws AuthenticationException {
|
||||
|
||||
Args.notNull(host, "Auth host");
|
||||
Args.notNull(credentialsProvider, "CredentialsProvider");
|
||||
|
||||
final Credentials credentials = credentialsProvider.getCredentials(new AuthScope(host, null, getName()));
|
||||
if (credentials instanceof KerberosCredentials) {
|
||||
this.gssCredential = ((KerberosCredentials) credentials).getGSSCredential();
|
||||
} else {
|
||||
this.gssCredential = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getPrinciple() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateAuthResponse(
|
||||
final HttpHost host,
|
||||
final HttpRequest request,
|
||||
final HttpContext context) throws AuthenticationException {
|
||||
Args.notNull(host, "HTTP host");
|
||||
Args.notNull(request, "HTTP request");
|
||||
switch (state) {
|
||||
case UNINITIATED:
|
||||
throw new AuthenticationException(getSchemeName() + " authentication has not been initiated");
|
||||
throw new AuthenticationException(getName() + " authentication has not been initiated");
|
||||
case FAILED:
|
||||
throw new AuthenticationException(getSchemeName() + " authentication has failed");
|
||||
throw new AuthenticationException(getName() + " authentication has failed");
|
||||
case CHALLENGE_RECEIVED:
|
||||
try {
|
||||
final HttpRoute route = (HttpRoute) context.getAttribute(HttpClientContext.HTTP_ROUTE);
|
||||
if (route == null) {
|
||||
throw new AuthenticationException("Connection route is not available");
|
||||
}
|
||||
HttpHost host;
|
||||
if (isProxy()) {
|
||||
host = route.getProxyHost();
|
||||
if (host == null) {
|
||||
host = route.getTargetHost();
|
||||
}
|
||||
} else {
|
||||
host = route.getTargetHost();
|
||||
}
|
||||
final String authServer;
|
||||
String hostname = host.getHostName();
|
||||
|
||||
if (this.useCanonicalHostname){
|
||||
try {
|
||||
//TODO: uncomment this statement and delete the resolveCanonicalHostname,
|
||||
|
@ -208,7 +206,7 @@ public abstract class GGSSchemeBase extends NonStandardAuthScheme {
|
|||
if (log.isDebugEnabled()) {
|
||||
log.debug("init " + authServer);
|
||||
}
|
||||
token = generateToken(token, authServer, credentials);
|
||||
token = generateToken(token, authServer);
|
||||
state = State.TOKEN_GENERATED;
|
||||
} catch (final GSSException gsse) {
|
||||
state = State.FAILED;
|
||||
|
@ -233,15 +231,7 @@ public abstract class GGSSchemeBase extends NonStandardAuthScheme {
|
|||
if (log.isDebugEnabled()) {
|
||||
log.debug("Sending response '" + tokenstr + "' back to the auth server");
|
||||
}
|
||||
final CharArrayBuffer buffer = new CharArrayBuffer(32);
|
||||
if (isProxy()) {
|
||||
buffer.append(HttpHeaders.PROXY_AUTHORIZATION);
|
||||
} else {
|
||||
buffer.append(HttpHeaders.AUTHORIZATION);
|
||||
}
|
||||
buffer.append(": Negotiate ");
|
||||
buffer.append(tokenstr);
|
||||
return new BufferedHeader(buffer);
|
||||
return "Negotiate " + tokenstr;
|
||||
default:
|
||||
throw new IllegalStateException("Illegal state: " + state);
|
||||
}
|
||||
|
@ -256,4 +246,9 @@ public abstract class GGSSchemeBase extends NonStandardAuthScheme {
|
|||
return canonicalServer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + this.state + " " + challenge + ']';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -47,20 +47,18 @@ import org.apache.http.HttpResponse;
|
|||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.ParseException;
|
||||
import org.apache.http.auth.AuthChallenge;
|
||||
import org.apache.http.auth.AuthOption;
|
||||
import org.apache.http.auth.AuthProtocolState;
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.AuthState;
|
||||
import org.apache.http.auth.AuthenticationException;
|
||||
import org.apache.http.auth.ChallengeType;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.auth.CredentialsProvider;
|
||||
import org.apache.http.auth.MalformedChallengeException;
|
||||
import org.apache.http.client.AuthCache;
|
||||
import org.apache.http.client.AuthenticationStrategy;
|
||||
import org.apache.http.client.config.AuthSchemes;
|
||||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.message.ParserCursor;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.util.Asserts;
|
||||
|
@ -195,12 +193,12 @@ public class HttpAuthenticator {
|
|||
case UNCHALLENGED:
|
||||
final AuthScheme authScheme = authState.getAuthScheme();
|
||||
if (authScheme != null) {
|
||||
final String id = authScheme.getSchemeName();
|
||||
final String id = authScheme.getName();
|
||||
final AuthChallenge challenge = challengeMap.get(id.toLowerCase(Locale.ROOT));
|
||||
if (challenge != null) {
|
||||
this.log.debug("Authorization challenge processed");
|
||||
try {
|
||||
authScheme.processChallenge(challengeType, challenge);
|
||||
authScheme.processChallenge(challenge, context);
|
||||
} catch (MalformedChallengeException ex) {
|
||||
if (this.log.isWarnEnabled()) {
|
||||
this.log.warn(ex.getMessage());
|
||||
|
@ -209,7 +207,7 @@ public class HttpAuthenticator {
|
|||
authState.reset();
|
||||
return false;
|
||||
}
|
||||
if (authScheme.isComplete()) {
|
||||
if (authScheme.isChallengeComplete()) {
|
||||
this.log.debug("Authentication failed");
|
||||
clearCache(host, clientContext);
|
||||
authState.reset();
|
||||
|
@ -233,22 +231,16 @@ public class HttpAuthenticator {
|
|||
return false;
|
||||
}
|
||||
|
||||
final Queue<AuthOption> authOptions = new LinkedList<>();
|
||||
final Queue<AuthScheme> authOptions = new LinkedList<>();
|
||||
for (AuthScheme authScheme: preferredSchemes) {
|
||||
try {
|
||||
final String id = authScheme.getSchemeName();
|
||||
final String id = authScheme.getName();
|
||||
final AuthChallenge challenge = challengeMap.get(id.toLowerCase(Locale.ROOT));
|
||||
authScheme.processChallenge(challengeType, challenge);
|
||||
final AuthScope authScope = new AuthScope(
|
||||
host.getHostName(),
|
||||
host.getPort(),
|
||||
authScheme.getRealm(),
|
||||
authScheme.getSchemeName());
|
||||
final Credentials credentials = credsProvider.getCredentials(authScope);
|
||||
if (credentials != null) {
|
||||
authOptions.add(new AuthOption(authScheme, credentials));
|
||||
authScheme.processChallenge(challenge, context);
|
||||
if (authScheme.isResponseReady(host, credsProvider, context)) {
|
||||
authOptions.add(authScheme);
|
||||
}
|
||||
} catch (MalformedChallengeException ex) {
|
||||
} catch (AuthenticationException | MalformedChallengeException ex) {
|
||||
if (this.log.isWarnEnabled()) {
|
||||
this.log.warn(ex.getMessage());
|
||||
}
|
||||
|
@ -267,11 +259,12 @@ public class HttpAuthenticator {
|
|||
}
|
||||
|
||||
public void addAuthResponse(
|
||||
final HttpHost host,
|
||||
final ChallengeType challengeType,
|
||||
final HttpRequest request,
|
||||
final AuthState authState,
|
||||
final HttpContext context) throws HttpException, IOException {
|
||||
AuthScheme authScheme = authState.getAuthScheme();
|
||||
Credentials creds = authState.getCredentials();
|
||||
switch (authState.getState()) {
|
||||
case FAILURE:
|
||||
return;
|
||||
|
@ -285,19 +278,20 @@ public class HttpAuthenticator {
|
|||
Asserts.notNull(authScheme, "AuthScheme");
|
||||
break;
|
||||
case CHALLENGED:
|
||||
final Queue<AuthOption> authOptions = authState.getAuthOptions();
|
||||
final Queue<AuthScheme> authOptions = authState.getAuthOptions();
|
||||
if (authOptions != null) {
|
||||
while (!authOptions.isEmpty()) {
|
||||
final AuthOption authOption = authOptions.remove();
|
||||
authScheme = authOption.getAuthScheme();
|
||||
creds = authOption.getCredentials();
|
||||
authState.update(authScheme, creds);
|
||||
authScheme = authOptions.remove();
|
||||
authState.update(authScheme);
|
||||
if (this.log.isDebugEnabled()) {
|
||||
this.log.debug("Generating response to an authentication challenge using "
|
||||
+ authScheme.getSchemeName() + " scheme");
|
||||
+ authScheme.getName() + " scheme");
|
||||
}
|
||||
try {
|
||||
final Header header = doAuth(authScheme, creds, request, context);
|
||||
final String authResponse = authScheme.generateAuthResponse(host, request, context);
|
||||
final Header header = new BasicHeader(
|
||||
challengeType == ChallengeType.TARGET ? HttpHeaders.AUTHORIZATION : HttpHeaders.PROXY_AUTHORIZATION,
|
||||
authResponse);
|
||||
request.addHeader(header);
|
||||
break;
|
||||
} catch (final AuthenticationException ex) {
|
||||
|
@ -314,7 +308,10 @@ public class HttpAuthenticator {
|
|||
}
|
||||
if (authScheme != null) {
|
||||
try {
|
||||
final Header header = doAuth(authScheme, creds, request, context);
|
||||
final String authResponse = authScheme.generateAuthResponse(host, request, context);
|
||||
final Header header = new BasicHeader(
|
||||
challengeType == ChallengeType.TARGET ? HttpHeaders.AUTHORIZATION : HttpHeaders.PROXY_AUTHORIZATION,
|
||||
authResponse);
|
||||
request.addHeader(header);
|
||||
} catch (final AuthenticationException ex) {
|
||||
if (this.log.isErrorEnabled()) {
|
||||
|
@ -325,7 +322,7 @@ public class HttpAuthenticator {
|
|||
}
|
||||
|
||||
private boolean isCachable(final AuthScheme authScheme) {
|
||||
final String schemeName = authScheme.getSchemeName();
|
||||
final String schemeName = authScheme.getName();
|
||||
return schemeName.equalsIgnoreCase(AuthSchemes.BASIC) ||
|
||||
schemeName.equalsIgnoreCase(AuthSchemes.DIGEST);
|
||||
}
|
||||
|
@ -335,7 +332,7 @@ public class HttpAuthenticator {
|
|||
final AuthCache authCache = clientContext.getAuthCache();
|
||||
if (authCache != null) {
|
||||
if (this.log.isDebugEnabled()) {
|
||||
this.log.debug("Caching '" + authScheme.getSchemeName() + "' auth scheme for " + host);
|
||||
this.log.debug("Caching '" + authScheme.getName() + "' auth scheme for " + host);
|
||||
}
|
||||
authCache.put(host, authScheme);
|
||||
}
|
||||
|
@ -353,12 +350,4 @@ public class HttpAuthenticator {
|
|||
}
|
||||
}
|
||||
|
||||
private Header doAuth(
|
||||
final AuthScheme authScheme,
|
||||
final Credentials creds,
|
||||
final HttpRequest request,
|
||||
final HttpContext context) throws AuthenticationException {
|
||||
return authScheme.authenticate(creds, request, context);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
package org.apache.http.impl.auth;
|
||||
|
||||
import org.apache.http.annotation.NotThreadSafe;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.ietf.jgss.GSSException;
|
||||
import org.ietf.jgss.Oid;
|
||||
|
||||
|
@ -57,13 +56,13 @@ public class KerberosScheme extends GGSSchemeBase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getSchemeName() {
|
||||
public String getName() {
|
||||
return "Kerberos";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] generateToken(final byte[] input, final String authServer, final Credentials credentials) throws GSSException {
|
||||
return generateGSSToken(input, new Oid(KERBEROS_OID), authServer, credentials);
|
||||
protected byte[] generateToken(final byte[] input, final String authServer) throws GSSException {
|
||||
return generateGSSToken(input, new Oid(KERBEROS_OID), authServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1574,7 +1574,7 @@ final class NTLMEngineImpl implements NTLMEngine {
|
|||
i++;
|
||||
}
|
||||
|
||||
// Very important: update the digest with the ipad buffer
|
||||
// Very important: processChallenge the digest with the ipad buffer
|
||||
md5.reset();
|
||||
md5.update(ipad);
|
||||
|
||||
|
|
|
@ -26,21 +26,21 @@
|
|||
*/
|
||||
package org.apache.http.impl.auth;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpHeaders;
|
||||
import java.security.Principal;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.annotation.NotThreadSafe;
|
||||
import org.apache.http.auth.AuthChallenge;
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.AuthenticationException;
|
||||
import org.apache.http.auth.ChallengeType;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.auth.InvalidCredentialsException;
|
||||
import org.apache.http.auth.CredentialsProvider;
|
||||
import org.apache.http.auth.MalformedChallengeException;
|
||||
import org.apache.http.auth.NTCredentials;
|
||||
import org.apache.http.message.BufferedHeader;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.util.Args;
|
||||
import org.apache.http.util.CharArrayBuffer;
|
||||
|
||||
/**
|
||||
* NTLM is a proprietary authentication scheme developed by Microsoft
|
||||
|
@ -49,7 +49,7 @@ import org.apache.http.util.CharArrayBuffer;
|
|||
* @since 4.0
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public class NTLMScheme extends NonStandardAuthScheme {
|
||||
public class NTLMScheme implements AuthScheme {
|
||||
|
||||
enum State {
|
||||
UNINITIATED,
|
||||
|
@ -63,6 +63,8 @@ public class NTLMScheme extends NonStandardAuthScheme {
|
|||
private final NTLMEngine engine;
|
||||
|
||||
private State state;
|
||||
private String challenge;
|
||||
private NTCredentials credentials;
|
||||
|
||||
public NTLMScheme(final NTLMEngine engine) {
|
||||
super();
|
||||
|
@ -79,7 +81,7 @@ public class NTLMScheme extends NonStandardAuthScheme {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getSchemeName() {
|
||||
public String getName() {
|
||||
return "ntlm";
|
||||
}
|
||||
|
||||
|
@ -88,13 +90,21 @@ public class NTLMScheme extends NonStandardAuthScheme {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRealm() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processChallenge(
|
||||
final ChallengeType challengeType, final AuthChallenge authChallenge) throws MalformedChallengeException {
|
||||
Args.notNull(challengeType, "ChallengeType");
|
||||
final AuthChallenge authChallenge,
|
||||
final HttpContext context) throws MalformedChallengeException {
|
||||
Args.notNull(authChallenge, "AuthChallenge");
|
||||
final String value = authChallenge.getValue();
|
||||
if (value == null || value.isEmpty()) {
|
||||
if (authChallenge.getValue() == null) {
|
||||
throw new MalformedChallengeException("Missing auth challenge");
|
||||
}
|
||||
this.challenge = authChallenge.getValue();
|
||||
if (this.challenge == null || this.challenge.isEmpty()) {
|
||||
if (this.state == State.UNINITIATED) {
|
||||
this.state = State.CHALLENGE_RECEIVED;
|
||||
} else {
|
||||
|
@ -111,51 +121,66 @@ public class NTLMScheme extends NonStandardAuthScheme {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Header authenticate(
|
||||
final Credentials credentials,
|
||||
public boolean isResponseReady(
|
||||
final HttpHost host,
|
||||
final CredentialsProvider credentialsProvider,
|
||||
final HttpContext context) throws AuthenticationException {
|
||||
|
||||
Args.notNull(host, "Auth host");
|
||||
Args.notNull(credentialsProvider, "CredentialsProvider");
|
||||
|
||||
final Credentials credentials = credentialsProvider.getCredentials(new AuthScope(host, null, getName()));
|
||||
if (credentials instanceof NTCredentials) {
|
||||
this.credentials = (NTCredentials) credentials;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getPrinciple() {
|
||||
return this.credentials != null ? this.credentials.getUserPrincipal() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateAuthResponse(
|
||||
final HttpHost host,
|
||||
final HttpRequest request,
|
||||
final HttpContext context) throws AuthenticationException {
|
||||
final NTCredentials ntcredentials;
|
||||
try {
|
||||
ntcredentials = (NTCredentials) credentials;
|
||||
} catch (final ClassCastException e) {
|
||||
throw new InvalidCredentialsException(
|
||||
"Credentials cannot be used for NTLM authentication: "
|
||||
+ credentials.getClass().getName());
|
||||
if (this.credentials == null) {
|
||||
throw new AuthenticationException("NT credentials not available");
|
||||
}
|
||||
final String response;
|
||||
if (this.state == State.FAILED) {
|
||||
throw new AuthenticationException("NTLM authentication failed");
|
||||
} else if (this.state == State.CHALLENGE_RECEIVED) {
|
||||
response = this.engine.generateType1Msg(
|
||||
ntcredentials.getNetbiosDomain(),
|
||||
ntcredentials.getWorkstation());
|
||||
this.credentials.getNetbiosDomain(),
|
||||
this.credentials.getWorkstation());
|
||||
this.state = State.MSG_TYPE1_GENERATED;
|
||||
} else if (this.state == State.MSG_TYPE2_RECEVIED) {
|
||||
response = this.engine.generateType3Msg(
|
||||
ntcredentials.getUserName(),
|
||||
ntcredentials.getPassword(),
|
||||
ntcredentials.getNetbiosDomain(),
|
||||
ntcredentials.getWorkstation(),
|
||||
getChallenge());
|
||||
this.credentials.getUserName(),
|
||||
this.credentials.getPassword(),
|
||||
this.credentials.getNetbiosDomain(),
|
||||
this.credentials.getWorkstation(),
|
||||
this.challenge);
|
||||
this.state = State.MSG_TYPE3_GENERATED;
|
||||
} else {
|
||||
throw new AuthenticationException("Unexpected state: " + this.state);
|
||||
}
|
||||
final CharArrayBuffer buffer = new CharArrayBuffer(32);
|
||||
if (isProxy()) {
|
||||
buffer.append(HttpHeaders.PROXY_AUTHORIZATION);
|
||||
} else {
|
||||
buffer.append(HttpHeaders.AUTHORIZATION);
|
||||
}
|
||||
buffer.append(": NTLM ");
|
||||
buffer.append(response);
|
||||
return new BufferedHeader(buffer);
|
||||
return "NTLM " + response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isComplete() {
|
||||
public boolean isChallengeComplete() {
|
||||
return this.state == State.MSG_TYPE3_GENERATED || this.state == State.FAILED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + this.state + " " + challenge + ']';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.auth.AuthChallenge;
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.ChallengeType;
|
||||
import org.apache.http.auth.MalformedChallengeException;
|
||||
|
||||
public abstract class NonStandardAuthScheme implements AuthScheme {
|
||||
|
||||
private ChallengeType challengeType;
|
||||
private String challenge;
|
||||
|
||||
public boolean isProxy() {
|
||||
return this.challengeType != null && this.challengeType == ChallengeType.PROXY;
|
||||
}
|
||||
|
||||
protected void update(final ChallengeType challengeType, final AuthChallenge authChallenge) throws MalformedChallengeException{
|
||||
if (authChallenge.getValue() == null) {
|
||||
throw new MalformedChallengeException("Missing auth challenge");
|
||||
}
|
||||
this.challengeType = challengeType;
|
||||
this.challenge = authChallenge.getValue();
|
||||
}
|
||||
|
||||
protected String getChallenge() {
|
||||
return this.challenge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameter(final String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRealm() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getSchemeName() + "(" + this.challengeType + ") " + this.challenge;
|
||||
}
|
||||
|
||||
}
|
|
@ -27,7 +27,6 @@
|
|||
package org.apache.http.impl.auth;
|
||||
|
||||
import org.apache.http.annotation.NotThreadSafe;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.ietf.jgss.GSSException;
|
||||
import org.ietf.jgss.Oid;
|
||||
|
||||
|
@ -58,13 +57,13 @@ public class SPNegoScheme extends GGSSchemeBase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getSchemeName() {
|
||||
public String getName() {
|
||||
return "Negotiate";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] generateToken(final byte[] input, final String authServer, final Credentials credentials) throws GSSException {
|
||||
return generateGSSToken(input, new Oid(SPNEGO_OID), authServer, credentials);
|
||||
protected byte[] generateToken(final byte[] input, final String authServer) throws GSSException {
|
||||
return generateGSSToken(input, new Oid(SPNEGO_OID), authServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.io.Serializable;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.annotation.NotThreadSafe;
|
||||
import org.apache.http.auth.AuthChallenge;
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.ChallengeType;
|
||||
import org.apache.http.auth.MalformedChallengeException;
|
||||
|
||||
/**
|
||||
* Abstract authentication scheme class that lays foundation for standard HTTP authentication schemes and
|
||||
* provides capabilities common to all authentication schemes defined in the HTTP specification.
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public abstract class StandardAuthScheme implements AuthScheme, Serializable {
|
||||
|
||||
private static final long serialVersionUID = -2845454858205884623L;
|
||||
|
||||
private final Map<String, String> paramMap;
|
||||
private ChallengeType challengeType;
|
||||
|
||||
/**
|
||||
* @since 4.3
|
||||
*/
|
||||
public StandardAuthScheme() {
|
||||
super();
|
||||
this.paramMap = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
protected void update(final ChallengeType challengeType, final AuthChallenge authChallenge) throws MalformedChallengeException {
|
||||
final List<NameValuePair> params = authChallenge.getParams();
|
||||
this.challengeType = challengeType;
|
||||
if (params != null) {
|
||||
for (NameValuePair param: params) {
|
||||
this.paramMap.put(param.getName().toLowerCase(Locale.ROOT), param.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRealm() {
|
||||
return getParameter("realm");
|
||||
}
|
||||
|
||||
protected Map<String, String> getParameters() {
|
||||
return this.paramMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@Override
|
||||
public String getParameter(final String name) {
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
return this.paramMap.get(name.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if authenticating against a proxy, {@code false}
|
||||
* otherwise.
|
||||
*/
|
||||
public boolean isProxy() {
|
||||
return this.challengeType != null && this.challengeType == ChallengeType.PROXY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getSchemeName() + "(" + this.challengeType + ") " + this.paramMap;
|
||||
}
|
||||
|
||||
}
|
|
@ -34,7 +34,6 @@ import org.apache.http.HttpConnection;
|
|||
import org.apache.http.annotation.Immutable;
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.AuthState;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.client.UserTokenHandler;
|
||||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.conn.ManagedHttpClientConnection;
|
||||
|
@ -90,11 +89,8 @@ public class DefaultUserTokenHandler implements UserTokenHandler {
|
|||
|
||||
private static Principal getAuthPrincipal(final AuthState authState) {
|
||||
final AuthScheme scheme = authState.getAuthScheme();
|
||||
if (scheme != null && scheme.isComplete() && scheme.isConnectionBased()) {
|
||||
final Credentials creds = authState.getCredentials();
|
||||
if (creds != null) {
|
||||
return creds.getUserPrincipal();
|
||||
}
|
||||
if (scheme != null && scheme.isConnectionBased()) {
|
||||
return scheme.getPrinciple();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@ public class ProxyClient {
|
|||
conn.bind(socket);
|
||||
}
|
||||
|
||||
this.authenticator.addAuthResponse(connect, this.proxyAuthState, context);
|
||||
this.authenticator.addAuthResponse(proxy, ChallengeType.PROXY, connect, this.proxyAuthState, context);
|
||||
|
||||
response = this.requestExec.execute(connect, conn, context);
|
||||
|
||||
|
|
|
@ -248,13 +248,15 @@ public class MainClientExec implements ClientExecChain {
|
|||
if (this.log.isDebugEnabled()) {
|
||||
this.log.debug("Target auth state: " + targetAuthState.getState());
|
||||
}
|
||||
this.authenticator.addAuthResponse(request, targetAuthState, context);
|
||||
this.authenticator.addAuthResponse(
|
||||
route.getTargetHost(), ChallengeType.TARGET, request, targetAuthState, context);
|
||||
}
|
||||
if (!request.containsHeader(HttpHeaders.PROXY_AUTHORIZATION) && !route.isTunnelled()) {
|
||||
if (this.log.isDebugEnabled()) {
|
||||
this.log.debug("Proxy auth state: " + proxyAuthState.getState());
|
||||
}
|
||||
this.authenticator.addAuthResponse(request, proxyAuthState, context);
|
||||
this.authenticator.addAuthResponse(
|
||||
route.getProxyHost(), ChallengeType.PROXY, request, proxyAuthState, context);
|
||||
}
|
||||
|
||||
response = requestExecutor.execute(request, managedConn, context);
|
||||
|
@ -423,7 +425,7 @@ public class MainClientExec implements ClientExecChain {
|
|||
* The connection must be established to the (last) proxy.
|
||||
* A CONNECT request for tunnelling through the proxy will
|
||||
* be created and sent, the response received and checked.
|
||||
* This method does <i>not</i> update the connection with
|
||||
* This method does <i>not</i> processChallenge the connection with
|
||||
* information about the tunnel, that is left to the caller.
|
||||
*/
|
||||
private boolean createTunnelToTarget(
|
||||
|
@ -455,7 +457,7 @@ public class MainClientExec implements ClientExecChain {
|
|||
}
|
||||
|
||||
connect.removeHeaders(HttpHeaders.PROXY_AUTHORIZATION);
|
||||
this.authenticator.addAuthResponse(connect, proxyAuthState, context);
|
||||
this.authenticator.addAuthResponse(proxy, ChallengeType.PROXY, connect, proxyAuthState, context);
|
||||
|
||||
response = this.requestExecutor.execute(connect, managedConn, context);
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ import org.apache.http.util.Args;
|
|||
* Request executor in the request execution chain that is responsible
|
||||
* for implementation of HTTP specification requirements.
|
||||
* Internally this executor relies on a {@link HttpProcessor} to populate
|
||||
* requisite HTTP request headers, process HTTP response headers and update
|
||||
* requisite HTTP request headers, process HTTP response headers and processChallenge
|
||||
* session state in {@link HttpClientContext}.
|
||||
* <p>
|
||||
* Further responsibilities such as communication with the opposite
|
||||
|
|
|
@ -113,9 +113,7 @@ public class TestRequestAuthCache {
|
|||
final HttpRequestInterceptor interceptor = new RequestAuthCache();
|
||||
interceptor.process(request, context);
|
||||
Assert.assertNotNull(this.targetState.getAuthScheme());
|
||||
Assert.assertSame(this.creds1, this.targetState.getCredentials());
|
||||
Assert.assertNotNull(this.proxyState.getAuthScheme());
|
||||
Assert.assertSame(this.creds2, this.proxyState.getCredentials());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -138,9 +136,7 @@ public class TestRequestAuthCache {
|
|||
final HttpRequestInterceptor interceptor = new RequestAuthCache();
|
||||
interceptor.process(request, context);
|
||||
Assert.assertNull(this.targetState.getAuthScheme());
|
||||
Assert.assertNull(this.targetState.getCredentials());
|
||||
Assert.assertNull(this.proxyState.getAuthScheme());
|
||||
Assert.assertNull(this.proxyState.getCredentials());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -158,9 +154,7 @@ public class TestRequestAuthCache {
|
|||
final HttpRequestInterceptor interceptor = new RequestAuthCache();
|
||||
interceptor.process(request, context);
|
||||
Assert.assertNull(this.targetState.getAuthScheme());
|
||||
Assert.assertNull(this.targetState.getCredentials());
|
||||
Assert.assertNull(this.proxyState.getAuthScheme());
|
||||
Assert.assertNull(this.proxyState.getCredentials());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -180,36 +174,7 @@ public class TestRequestAuthCache {
|
|||
final HttpRequestInterceptor interceptor = new RequestAuthCache();
|
||||
interceptor.process(request, context);
|
||||
Assert.assertNull(this.targetState.getAuthScheme());
|
||||
Assert.assertNull(this.targetState.getCredentials());
|
||||
Assert.assertNull(this.proxyState.getAuthScheme());
|
||||
Assert.assertNull(this.proxyState.getCredentials());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoMatchingCredentials() throws Exception {
|
||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||
|
||||
this.credProvider.clear();
|
||||
|
||||
final HttpClientContext context = HttpClientContext.create();
|
||||
context.setAttribute(HttpClientContext.CREDS_PROVIDER, this.credProvider);
|
||||
context.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, this.target);
|
||||
context.setAttribute(HttpClientContext.HTTP_ROUTE, new HttpRoute(this.target, null, this.proxy, false));
|
||||
context.setAttribute(HttpClientContext.TARGET_AUTH_STATE, this.targetState);
|
||||
context.setAttribute(HttpClientContext.PROXY_AUTH_STATE, this.proxyState);
|
||||
|
||||
final AuthCache authCache = new BasicAuthCache();
|
||||
authCache.put(this.target, this.authscheme1);
|
||||
authCache.put(this.proxy, this.authscheme2);
|
||||
|
||||
context.setAttribute(HttpClientContext.AUTH_CACHE, authCache);
|
||||
|
||||
final HttpRequestInterceptor interceptor = new RequestAuthCache();
|
||||
interceptor.process(request, context);
|
||||
Assert.assertNull(this.targetState.getAuthScheme());
|
||||
Assert.assertNull(this.targetState.getCredentials());
|
||||
Assert.assertNull(this.proxyState.getAuthScheme());
|
||||
Assert.assertNull(this.proxyState.getCredentials());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -230,16 +195,14 @@ public class TestRequestAuthCache {
|
|||
context.setAttribute(HttpClientContext.AUTH_CACHE, authCache);
|
||||
|
||||
this.targetState.setState(AuthProtocolState.CHALLENGED);
|
||||
this.targetState.update(new BasicScheme(), new UsernamePasswordCredentials("user3", "secret3"));
|
||||
this.targetState.update(new BasicScheme());
|
||||
this.proxyState.setState(AuthProtocolState.CHALLENGED);
|
||||
this.proxyState.update(new BasicScheme(), new UsernamePasswordCredentials("user4", "secret4"));
|
||||
this.proxyState.update(new BasicScheme());
|
||||
|
||||
final HttpRequestInterceptor interceptor = new RequestAuthCache();
|
||||
interceptor.process(request, context);
|
||||
Assert.assertNotSame(this.authscheme1, this.targetState.getAuthScheme());
|
||||
Assert.assertNotSame(this.creds1, this.targetState.getCredentials());
|
||||
Assert.assertNotSame(this.authscheme2, this.proxyState.getAuthScheme());
|
||||
Assert.assertNotSame(this.creds2, this.proxyState.getCredentials());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,17 +34,15 @@ import java.util.List;
|
|||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpHeaders;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.auth.AuthChallenge;
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.ChallengeType;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.message.BasicHttpRequest;
|
||||
import org.apache.http.message.ParserCursor;
|
||||
import org.apache.http.protocol.BasicHttpContext;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.util.CharArrayBuffer;
|
||||
import org.apache.http.util.EncodingUtils;
|
||||
import org.junit.Assert;
|
||||
|
@ -69,7 +67,7 @@ public class TestBasicScheme {
|
|||
final String challenge = "Basic";
|
||||
final AuthChallenge authChallenge = parse(challenge);
|
||||
final AuthScheme authscheme = new BasicScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
Assert.assertNull(authscheme.getRealm());
|
||||
}
|
||||
|
||||
|
@ -81,56 +79,66 @@ public class TestBasicScheme {
|
|||
buffer.append((char)germanChar);
|
||||
}
|
||||
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, "some realm", null);
|
||||
final UsernamePasswordCredentials creds = new UsernamePasswordCredentials("dh", buffer.toString());
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
final BasicScheme authscheme = new BasicScheme(Consts.ISO_8859_1);
|
||||
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
final Header header = authscheme.authenticate(creds, request, context);
|
||||
Assert.assertEquals("Basic ZGg65C32Lfw=", header.getValue());
|
||||
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||
Assert.assertEquals("Basic ZGg65C32Lfw=", authResponse);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicAuthentication() throws Exception {
|
||||
final UsernamePasswordCredentials creds = new UsernamePasswordCredentials("testuser", "testpass");
|
||||
|
||||
final AuthChallenge authChallenge = parse("Basic realm=\"test\"");
|
||||
|
||||
final BasicScheme authscheme = new BasicScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, "test", null);
|
||||
final UsernamePasswordCredentials creds = new UsernamePasswordCredentials("testuser", "testpass");
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
final Header authResponse = authscheme.authenticate(creds, request, context);
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||
|
||||
final String expected = "Basic " + EncodingUtils.getAsciiString(
|
||||
Base64.encodeBase64(EncodingUtils.getAsciiBytes("testuser:testpass")));
|
||||
Assert.assertEquals(HttpHeaders.AUTHORIZATION, authResponse.getName());
|
||||
Assert.assertEquals(expected, authResponse.getValue());
|
||||
Assert.assertEquals(expected, authResponse);
|
||||
Assert.assertEquals("test", authscheme.getRealm());
|
||||
Assert.assertTrue(authscheme.isComplete());
|
||||
Assert.assertTrue(authscheme.isChallengeComplete());
|
||||
Assert.assertFalse(authscheme.isConnectionBased());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicProxyAuthentication() throws Exception {
|
||||
final UsernamePasswordCredentials creds = new UsernamePasswordCredentials("testuser", "testpass");
|
||||
|
||||
final AuthChallenge authChallenge = parse("Basic realm=\"test\"");
|
||||
|
||||
final BasicScheme authscheme = new BasicScheme();
|
||||
authscheme.processChallenge(ChallengeType.PROXY, authChallenge);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, "test", null);
|
||||
final UsernamePasswordCredentials creds = new UsernamePasswordCredentials("testuser", "testpass");
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
final Header authResponse = authscheme.authenticate(creds, request, context);
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||
|
||||
final String expected = "Basic " + EncodingUtils.getAsciiString(
|
||||
Base64.encodeBase64(EncodingUtils.getAsciiBytes("testuser:testpass")));
|
||||
Assert.assertEquals(HttpHeaders.PROXY_AUTHORIZATION, authResponse.getName());
|
||||
Assert.assertEquals(expected, authResponse.getValue());
|
||||
Assert.assertEquals(expected, authResponse);
|
||||
Assert.assertEquals("test", authscheme.getRealm());
|
||||
Assert.assertTrue(authscheme.isComplete());
|
||||
Assert.assertTrue(authscheme.isChallengeComplete());
|
||||
Assert.assertFalse(authscheme.isConnectionBased());
|
||||
}
|
||||
|
||||
|
@ -139,7 +147,7 @@ public class TestBasicScheme {
|
|||
final AuthChallenge authChallenge = parse("Basic realm=\"test\"");
|
||||
|
||||
final BasicScheme basicScheme = new BasicScheme();
|
||||
basicScheme.processChallenge(ChallengeType.PROXY, authChallenge);
|
||||
basicScheme.processChallenge(authChallenge, null);
|
||||
|
||||
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
final ObjectOutputStream out = new ObjectOutputStream(buffer);
|
||||
|
@ -149,10 +157,9 @@ public class TestBasicScheme {
|
|||
final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(raw));
|
||||
final BasicScheme authScheme = (BasicScheme) in.readObject();
|
||||
|
||||
Assert.assertEquals(basicScheme.getSchemeName(), authScheme.getSchemeName());
|
||||
Assert.assertEquals(basicScheme.getName(), authScheme.getName());
|
||||
Assert.assertEquals(basicScheme.getRealm(), authScheme.getRealm());
|
||||
Assert.assertEquals(basicScheme.isComplete(), authScheme.isComplete());
|
||||
Assert.assertEquals(true, basicScheme.isProxy());
|
||||
Assert.assertEquals(basicScheme.isChallengeComplete(), authScheme.isChallengeComplete());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -167,10 +174,9 @@ public class TestBasicScheme {
|
|||
final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(raw));
|
||||
final BasicScheme authScheme = (BasicScheme) in.readObject();
|
||||
|
||||
Assert.assertEquals(basicScheme.getSchemeName(), authScheme.getSchemeName());
|
||||
Assert.assertEquals(basicScheme.getName(), authScheme.getName());
|
||||
Assert.assertEquals(basicScheme.getRealm(), authScheme.getRealm());
|
||||
Assert.assertEquals(basicScheme.isComplete(), authScheme.isComplete());
|
||||
Assert.assertEquals(false, basicScheme.isProxy());
|
||||
Assert.assertEquals(basicScheme.isChallengeComplete(), authScheme.isChallengeComplete());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,26 +36,25 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HeaderElement;
|
||||
import org.apache.http.HttpEntityEnclosingRequest;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.auth.AuthChallenge;
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.AuthenticationException;
|
||||
import org.apache.http.auth.ChallengeType;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.auth.MalformedChallengeException;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.entity.InputStreamEntity;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.message.BasicHeaderValueParser;
|
||||
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
|
||||
import org.apache.http.message.BasicHttpRequest;
|
||||
import org.apache.http.message.ParserCursor;
|
||||
import org.apache.http.protocol.BasicHttpContext;
|
||||
import org.apache.http.protocol.HTTP;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.util.CharArrayBuffer;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
@ -78,27 +77,33 @@ public class TestDigestScheme {
|
|||
public void testDigestAuthenticationEmptyChallenge1() throws Exception {
|
||||
final AuthChallenge authChallenge = parse("Digest");
|
||||
final AuthScheme authscheme = new DigestScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
}
|
||||
|
||||
@Test(expected=MalformedChallengeException.class)
|
||||
public void testDigestAuthenticationEmptyChallenge2() throws Exception {
|
||||
final AuthChallenge authChallenge = parse("Digest ");
|
||||
final AuthScheme authscheme = new DigestScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDigestAuthenticationWithDefaultCreds() throws Exception {
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, "realm1", null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final Credentials creds = new UsernamePasswordCredentials("username","password");
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
|
||||
final AuthChallenge authChallenge = parse(challenge);
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
||||
Assert.assertTrue(authscheme.isComplete());
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||
Assert.assertTrue(authscheme.isChallengeComplete());
|
||||
Assert.assertFalse(authscheme.isConnectionBased());
|
||||
|
||||
final Map<String, String> table = parseAuthResponse(authResponse);
|
||||
|
@ -111,14 +116,20 @@ public class TestDigestScheme {
|
|||
|
||||
@Test
|
||||
public void testDigestAuthentication() throws Exception {
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, "realm1", null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final Credentials creds = new UsernamePasswordCredentials("username","password");
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
|
||||
final AuthChallenge authChallenge = parse(challenge);
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||
|
||||
final Map<String, String> table = parseAuthResponse(authResponse);
|
||||
Assert.assertEquals("username", table.get("username"));
|
||||
|
@ -130,20 +141,29 @@ public class TestDigestScheme {
|
|||
|
||||
@Test
|
||||
public void testDigestAuthenticationInvalidInput() throws Exception {
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, "realm1", null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final Credentials creds = new UsernamePasswordCredentials("username","password");
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
|
||||
final AuthChallenge authChallenge = parse(challenge);
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
|
||||
try {
|
||||
authscheme.authenticate(null, request, context);
|
||||
authscheme.isResponseReady(null, credentialsProvider, null);
|
||||
Assert.fail("IllegalArgumentException should have been thrown");
|
||||
} catch (final IllegalArgumentException ex) {
|
||||
}
|
||||
try {
|
||||
authscheme.authenticate(cred, null, context);
|
||||
authscheme.isResponseReady(host, null, null);
|
||||
Assert.fail("IllegalArgumentException should have been thrown");
|
||||
} catch (final IllegalArgumentException ex) {
|
||||
}
|
||||
try {
|
||||
authscheme.generateAuthResponse(host, null, null);
|
||||
Assert.fail("IllegalArgumentException should have been thrown");
|
||||
} catch (final IllegalArgumentException ex) {
|
||||
}
|
||||
|
@ -151,16 +171,22 @@ public class TestDigestScheme {
|
|||
|
||||
@Test
|
||||
public void testDigestAuthenticationWithSHA() throws Exception {
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, "realm1", null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final Credentials creds = new UsernamePasswordCredentials("username","password");
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge = "Digest realm=\"realm1\", " +
|
||||
"nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
|
||||
"algorithm=SHA";
|
||||
final AuthChallenge authChallenge = parse(challenge);
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||
|
||||
final Map<String, String> table = parseAuthResponse(authResponse);
|
||||
Assert.assertEquals("username", table.get("username"));
|
||||
|
@ -172,14 +198,20 @@ public class TestDigestScheme {
|
|||
|
||||
@Test
|
||||
public void testDigestAuthenticationWithQueryStringInDigestURI() throws Exception {
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/?param=value");
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, "realm1", null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final Credentials creds = new UsernamePasswordCredentials("username","password");
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
|
||||
final AuthChallenge authChallenge = parse(challenge);
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/?param=value");
|
||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||
|
||||
final Map<String, String> table = parseAuthResponse(authResponse);
|
||||
Assert.assertEquals("username", table.get("username"));
|
||||
|
@ -189,64 +221,40 @@ public class TestDigestScheme {
|
|||
Assert.assertEquals("a847f58f5fef0bc087bcb9c3eb30e042", table.get("response"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDigestAuthenticationWithMultipleRealms() throws Exception {
|
||||
final String challenge1 = "Digest realm=\"realm1\", nonce=\"abcde\"";
|
||||
final String challenge2 = "Digest realm=\"realm2\", nonce=\"123546\"";
|
||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
||||
final Credentials cred2 = new UsernamePasswordCredentials("uname2","password2");
|
||||
|
||||
final AuthChallenge authChallenge1 = parse(challenge1);
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge1);
|
||||
Header authResponse = authscheme.authenticate(cred, request, context);
|
||||
|
||||
Map<String, String> table = parseAuthResponse(authResponse);
|
||||
Assert.assertEquals("username", table.get("username"));
|
||||
Assert.assertEquals("realm1", table.get("realm"));
|
||||
Assert.assertEquals("/", table.get("uri"));
|
||||
Assert.assertEquals("abcde", table.get("nonce"));
|
||||
Assert.assertEquals("786f500303eac1478f3c2865e676ed68", table.get("response"));
|
||||
|
||||
final AuthChallenge authChallenge2 = parse(challenge2);
|
||||
final DigestScheme authscheme2 = new DigestScheme();
|
||||
authscheme2.processChallenge(ChallengeType.TARGET, authChallenge2);
|
||||
authResponse = authscheme2.authenticate(cred2, request, context);
|
||||
|
||||
table = parseAuthResponse(authResponse);
|
||||
Assert.assertEquals("uname2", table.get("username"));
|
||||
Assert.assertEquals("realm2", table.get("realm"));
|
||||
Assert.assertEquals("/", table.get("uri"));
|
||||
Assert.assertEquals("123546", table.get("nonce"));
|
||||
Assert.assertEquals("0283edd9ef06a38b378b3b74661391e9", table.get("response"));
|
||||
}
|
||||
|
||||
@Test(expected=AuthenticationException.class)
|
||||
public void testDigestAuthenticationNoRealm() throws Exception {
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, "realm1", null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final Credentials creds = new UsernamePasswordCredentials("username","password");
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge = "Digest no-realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
|
||||
final AuthChallenge authChallenge = parse(challenge);
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
|
||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
authscheme.authenticate(cred, request, context);
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
authscheme.generateAuthResponse(host, request, null);
|
||||
}
|
||||
|
||||
@Test(expected=AuthenticationException.class)
|
||||
public void testDigestAuthenticationNoNonce() throws Exception {
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, "realm1", null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final Credentials creds = new UsernamePasswordCredentials("username","password");
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge = "Digest realm=\"realm1\", no-nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
|
||||
final AuthChallenge authChallenge = parse(challenge);
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
|
||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
authscheme.authenticate(cred, request, context);
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
authscheme.generateAuthResponse(host, request, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -261,6 +269,13 @@ public class TestDigestScheme {
|
|||
final String password="password";
|
||||
final String nonce="e273f1776275974f1a120d8b92c5b3cb";
|
||||
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, realm, null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final Credentials creds = new UsernamePasswordCredentials(username, password);
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge="Digest realm=\"" + realm + "\", "
|
||||
+ "nonce=\"" + nonce + "\", "
|
||||
+ "opaque=\"SomeString\", "
|
||||
|
@ -270,17 +285,14 @@ public class TestDigestScheme {
|
|||
|
||||
final AuthChallenge authChallenge = parse(challenge);
|
||||
|
||||
final Credentials cred = new UsernamePasswordCredentials(username, password);
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
||||
final String response = authResponse.getValue();
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
|
||||
Assert.assertTrue(response.indexOf("nc=00000001") > 0); // test for quotes
|
||||
Assert.assertTrue(response.indexOf("qop=auth") > 0); // test for quotes
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||
|
||||
Assert.assertTrue(authResponse.indexOf("nc=00000001") > 0); // test for quotes
|
||||
Assert.assertTrue(authResponse.indexOf("qop=auth") > 0); // test for quotes
|
||||
|
||||
final Map<String, String> table = parseAuthResponse(authResponse);
|
||||
Assert.assertEquals(username, table.get("username"));
|
||||
|
@ -308,6 +320,13 @@ public class TestDigestScheme {
|
|||
final String password="password";
|
||||
final String nonce="e273f1776275974f1a120d8b92c5b3cb";
|
||||
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, realm, null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final Credentials creds = new UsernamePasswordCredentials(username, password);
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge="Digest realm=\"" + realm + "\", "
|
||||
+ "nonce=\"" + nonce + "\", "
|
||||
+ "opaque=\"SomeString\", "
|
||||
|
@ -316,14 +335,10 @@ public class TestDigestScheme {
|
|||
|
||||
final AuthChallenge authChallenge = parse(challenge);
|
||||
|
||||
final Credentials cred = new UsernamePasswordCredentials(username, password);
|
||||
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||
|
||||
final Map<String, String> table = parseAuthResponse(authResponse);
|
||||
Assert.assertEquals(username, table.get("username"));
|
||||
|
@ -350,6 +365,13 @@ public class TestDigestScheme {
|
|||
final String password="password";
|
||||
final String nonce="e273f1776275974f1a120d8b92c5b3cb";
|
||||
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, realm, null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final Credentials creds = new UsernamePasswordCredentials(username, password);
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge="Digest realm=\"" + realm + "\", "
|
||||
+ "nonce=\"" + nonce + "\", "
|
||||
+ "opaque=\"SomeString\", "
|
||||
|
@ -360,12 +382,10 @@ public class TestDigestScheme {
|
|||
final AuthChallenge authChallenge = parse(challenge);
|
||||
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
|
||||
final Credentials cred = new UsernamePasswordCredentials(username, password);
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
authscheme.authenticate(cred, request, context);
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
authscheme.generateAuthResponse(host, request, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -380,6 +400,13 @@ public class TestDigestScheme {
|
|||
final String password="password";
|
||||
final String nonce="e273f1776275974f1a120d8b92c5b3cb";
|
||||
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, realm, null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final Credentials creds = new UsernamePasswordCredentials(username, password);
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge="Digest realm=\"" + realm + "\", "
|
||||
+ "nonce=\"" + nonce + "\", "
|
||||
+ "opaque=\"SomeString\", "
|
||||
|
@ -390,12 +417,10 @@ public class TestDigestScheme {
|
|||
final AuthChallenge authChallenge = parse(challenge);
|
||||
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
|
||||
final Credentials cred = new UsernamePasswordCredentials(username, password);
|
||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
authscheme.authenticate(cred, request, context);
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
authscheme.generateAuthResponse(host, request, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -404,17 +429,16 @@ public class TestDigestScheme {
|
|||
"nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", stale=\"true\"";
|
||||
final AuthChallenge authChallenge = parse(challenge);
|
||||
final AuthScheme authscheme = new DigestScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
|
||||
Assert.assertFalse(authscheme.isComplete());
|
||||
Assert.assertFalse(authscheme.isChallengeComplete());
|
||||
}
|
||||
|
||||
private static Map<String, String> parseAuthResponse(final Header authResponse) {
|
||||
final String s = authResponse.getValue();
|
||||
if (!s.startsWith("Digest ")) {
|
||||
private static Map<String, String> parseAuthResponse(final String authResponse) {
|
||||
if (!authResponse.startsWith("Digest ")) {
|
||||
return null;
|
||||
}
|
||||
final HeaderElement[] elements = BasicHeaderValueParser.parseElements(s.substring(7), null);
|
||||
final HeaderElement[] elements = BasicHeaderValueParser.parseElements(authResponse.substring(7), null);
|
||||
final Map<String, String> map = new HashMap<>(elements.length);
|
||||
for (final HeaderElement element : elements) {
|
||||
map.put(element.getName(), element.getValue());
|
||||
|
@ -424,50 +448,73 @@ public class TestDigestScheme {
|
|||
|
||||
@Test
|
||||
public void testDigestNouceCount() throws Exception {
|
||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, "realm1", null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final Credentials creds = new UsernamePasswordCredentials("username","password");
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge1 = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", qop=auth";
|
||||
final AuthChallenge authChallenge1 = parse(challenge1);
|
||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge1);
|
||||
final Header authResponse1 = authscheme.authenticate(cred, request, context);
|
||||
authscheme.processChallenge(authChallenge1, null);
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse1 = authscheme.generateAuthResponse(host, request, null);
|
||||
|
||||
final Map<String, String> table1 = parseAuthResponse(authResponse1);
|
||||
Assert.assertEquals("00000001", table1.get("nc"));
|
||||
final Header authResponse2 = authscheme.authenticate(cred, request, context);
|
||||
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse2 = authscheme.generateAuthResponse(host, request, null);
|
||||
|
||||
final Map<String, String> table2 = parseAuthResponse(authResponse2);
|
||||
Assert.assertEquals("00000002", table2.get("nc"));
|
||||
final String challenge2 = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", qop=auth";
|
||||
final AuthChallenge authChallenge2 = parse(challenge2);
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge2);
|
||||
final Header authResponse3 = authscheme.authenticate(cred, request, context);
|
||||
authscheme.processChallenge(authChallenge2, null);
|
||||
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse3 = authscheme.generateAuthResponse(host, request, null);
|
||||
|
||||
final Map<String, String> table3 = parseAuthResponse(authResponse3);
|
||||
Assert.assertEquals("00000003", table3.get("nc"));
|
||||
final String challenge3 = "Digest realm=\"realm1\", nonce=\"e273f1776275974f1a120d8b92c5b3cb\", qop=auth";
|
||||
final AuthChallenge authChallenge3 = parse(challenge3);
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge3);
|
||||
final Header authResponse4 = authscheme.authenticate(cred, request, context);
|
||||
authscheme.processChallenge(authChallenge3, null);
|
||||
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse4 = authscheme.generateAuthResponse(host, request, null);
|
||||
|
||||
final Map<String, String> table4 = parseAuthResponse(authResponse4);
|
||||
Assert.assertEquals("00000001", table4.get("nc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDigestMD5SessA1AndCnonceConsistency() throws Exception {
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, "subnet.domain.com", null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||
final Credentials creds = new UsernamePasswordCredentials("username","password");
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge1 = "Digest qop=\"auth\", algorithm=MD5-sess, nonce=\"1234567890abcdef\", " +
|
||||
"charset=utf-8, realm=\"subnet.domain.com\"";
|
||||
final AuthChallenge authChallenge1 = parse(challenge1);
|
||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge1);
|
||||
final Header authResponse1 = authscheme.authenticate(cred, request, context);
|
||||
authscheme.processChallenge(authChallenge1, null);
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse1 = authscheme.generateAuthResponse(host, request, null);
|
||||
|
||||
final Map<String, String> table1 = parseAuthResponse(authResponse1);
|
||||
Assert.assertEquals("00000001", table1.get("nc"));
|
||||
final String cnonce1 = authscheme.getCnonce();
|
||||
final String sessionKey1 = authscheme.getA1();
|
||||
|
||||
final Header authResponse2 = authscheme.authenticate(cred, request, context);
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse2 = authscheme.generateAuthResponse(host, request, null);
|
||||
final Map<String, String> table2 = parseAuthResponse(authResponse2);
|
||||
Assert.assertEquals("00000002", table2.get("nc"));
|
||||
final String cnonce2 = authscheme.getCnonce();
|
||||
|
@ -479,8 +526,9 @@ public class TestDigestScheme {
|
|||
final String challenge2 = "Digest qop=\"auth\", algorithm=MD5-sess, nonce=\"1234567890abcdef\", " +
|
||||
"charset=utf-8, realm=\"subnet.domain.com\"";
|
||||
final AuthChallenge authChallenge2 = parse(challenge2);
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge2);
|
||||
final Header authResponse3 = authscheme.authenticate(cred, request, context);
|
||||
authscheme.processChallenge(authChallenge2, null);
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse3 = authscheme.generateAuthResponse(host, request, null);
|
||||
final Map<String, String> table3 = parseAuthResponse(authResponse3);
|
||||
Assert.assertEquals("00000003", table3.get("nc"));
|
||||
|
||||
|
@ -493,8 +541,9 @@ public class TestDigestScheme {
|
|||
final String challenge3 = "Digest qop=\"auth\", algorithm=MD5-sess, nonce=\"fedcba0987654321\", " +
|
||||
"charset=utf-8, realm=\"subnet.domain.com\"";
|
||||
final AuthChallenge authChallenge3 = parse(challenge3);
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge3);
|
||||
final Header authResponse4 = authscheme.authenticate(cred, request, context);
|
||||
authscheme.processChallenge(authChallenge3, null);
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse4 = authscheme.generateAuthResponse(host, request, null);
|
||||
final Map<String, String> table4 = parseAuthResponse(authResponse4);
|
||||
Assert.assertEquals("00000001", table4.get("nc"));
|
||||
|
||||
|
@ -533,16 +582,21 @@ public class TestDigestScheme {
|
|||
|
||||
@Test
|
||||
public void testDigestAuthenticationQopAuthInt() throws Exception {
|
||||
final HttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("Post", "/");
|
||||
request.setEntity(new StringEntity("abc\u00e4\u00f6\u00fcabc", HTTP.DEF_CONTENT_CHARSET));
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, "realm1", null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final Credentials creds = new UsernamePasswordCredentials("username","password");
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
|
||||
"qop=\"auth,auth-int\"";
|
||||
final AuthChallenge authChallenge = parse(challenge);
|
||||
final HttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("Post", "/");
|
||||
request.setEntity(new StringEntity("abc\u00e4\u00f6\u00fcabc", HTTP.DEF_CONTENT_CHARSET));
|
||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||
|
||||
Assert.assertEquals("Post:/:acd2b59cd01c7737d8069015584c6cac", authscheme.getA2());
|
||||
|
||||
|
@ -556,15 +610,20 @@ public class TestDigestScheme {
|
|||
|
||||
@Test
|
||||
public void testDigestAuthenticationQopAuthIntNullEntity() throws Exception {
|
||||
final HttpRequest request = new BasicHttpEntityEnclosingRequest("Post", "/");
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, "realm1", null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final Credentials creds = new UsernamePasswordCredentials("username","password");
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
|
||||
"qop=\"auth,auth-int\"";
|
||||
final AuthChallenge authChallenge = parse(challenge);
|
||||
final HttpRequest request = new BasicHttpEntityEnclosingRequest("Post", "/");
|
||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||
|
||||
Assert.assertEquals("Post:/:d41d8cd98f00b204e9800998ecf8427e", authscheme.getA2());
|
||||
|
||||
|
@ -578,16 +637,21 @@ public class TestDigestScheme {
|
|||
|
||||
@Test
|
||||
public void testDigestAuthenticationQopAuthOrAuthIntNonRepeatableEntity() throws Exception {
|
||||
final HttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("Post", "/");
|
||||
request.setEntity(new InputStreamEntity(new ByteArrayInputStream(new byte[] {'a'}), -1));
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, "realm1", null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final Credentials creds = new UsernamePasswordCredentials("username","password");
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
|
||||
"qop=\"auth,auth-int\"";
|
||||
final AuthChallenge authChallenge = parse(challenge);
|
||||
final HttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("Post", "/");
|
||||
request.setEntity(new InputStreamEntity(new ByteArrayInputStream(new byte[] {'a'}), -1));
|
||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||
|
||||
Assert.assertEquals("Post:/", authscheme.getA2());
|
||||
|
||||
|
@ -601,32 +665,43 @@ public class TestDigestScheme {
|
|||
|
||||
@Test
|
||||
public void testParameterCaseSensitivity() throws Exception {
|
||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, "-", null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final Credentials creds = new UsernamePasswordCredentials("username","password");
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge = "Digest Realm=\"-\", " +
|
||||
"nonce=\"YjYuNGYyYmJhMzUuY2I5ZDhlZDE5M2ZlZDM 1Mjk3NGJkNTIyYjgyNTcwMjQ=\", " +
|
||||
"opaque=\"98700A3D9CE17065E2246B41035C6609\", qop=\"auth\"";
|
||||
final AuthChallenge authChallenge = parse(challenge);
|
||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
Assert.assertEquals("-", authscheme.getRealm());
|
||||
|
||||
authscheme.authenticate(cred, request, context);
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
authscheme.generateAuthResponse(host, request, null);
|
||||
}
|
||||
|
||||
@Test(expected=AuthenticationException.class)
|
||||
public void testDigestAuthenticationQopIntOnlyNonRepeatableEntity() throws Exception {
|
||||
final HttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("Post", "/");
|
||||
request.setEntity(new InputStreamEntity(new ByteArrayInputStream(new byte[] {'a'}), -1));
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final AuthScope authScope = new AuthScope(host, "realm1", null);
|
||||
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
final Credentials creds = new UsernamePasswordCredentials("username","password");
|
||||
credentialsProvider.setCredentials(authScope, creds);
|
||||
|
||||
final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
|
||||
"qop=\"auth-int\"";
|
||||
final AuthChallenge authChallenge = parse(challenge);
|
||||
final HttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("Post", "/");
|
||||
request.setEntity(new InputStreamEntity(new ByteArrayInputStream(new byte[] {'a'}), -1));
|
||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
||||
final DigestScheme authscheme = new DigestScheme();
|
||||
final HttpContext context = new BasicHttpContext();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
authscheme.authenticate(cred, request, context);
|
||||
authscheme.processChallenge(authChallenge, null);
|
||||
|
||||
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||
authscheme.generateAuthResponse(host, request, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -635,7 +710,7 @@ public class TestDigestScheme {
|
|||
"qop=\"auth,auth-int\"";
|
||||
final AuthChallenge authChallenge = parse(challenge);
|
||||
final DigestScheme digestScheme = new DigestScheme();
|
||||
digestScheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
||||
digestScheme.processChallenge(authChallenge, null);
|
||||
|
||||
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
final ObjectOutputStream out = new ObjectOutputStream(buffer);
|
||||
|
@ -645,9 +720,9 @@ public class TestDigestScheme {
|
|||
final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(raw));
|
||||
final DigestScheme authScheme = (DigestScheme) in.readObject();
|
||||
|
||||
Assert.assertEquals(digestScheme.getSchemeName(), authScheme.getSchemeName());
|
||||
Assert.assertEquals(digestScheme.getName(), authScheme.getName());
|
||||
Assert.assertEquals(digestScheme.getRealm(), authScheme.getRealm());
|
||||
Assert.assertEquals(digestScheme.isComplete(), authScheme.isComplete());
|
||||
Assert.assertEquals(digestScheme.isChallengeComplete(), authScheme.isChallengeComplete());
|
||||
Assert.assertEquals(digestScheme.getA1(), authScheme.getA1());
|
||||
Assert.assertEquals(digestScheme.getA2(), authScheme.getA2());
|
||||
Assert.assertEquals(digestScheme.getCnonce(), authScheme.getCnonce());
|
||||
|
|
|
@ -35,7 +35,6 @@ import org.apache.http.HttpRequest;
|
|||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.HttpVersion;
|
||||
import org.apache.http.auth.AuthOption;
|
||||
import org.apache.http.auth.AuthProtocolState;
|
||||
import org.apache.http.auth.AuthScheme;
|
||||
import org.apache.http.auth.AuthSchemeProvider;
|
||||
|
@ -44,11 +43,12 @@ import org.apache.http.auth.AuthState;
|
|||
import org.apache.http.auth.AuthenticationException;
|
||||
import org.apache.http.auth.ChallengeType;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.auth.CredentialsProvider;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.client.AuthCache;
|
||||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.config.Lookup;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.impl.client.DefaultAuthenticationStrategy;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.message.BasicHttpRequest;
|
||||
|
@ -68,8 +68,7 @@ public class TestHttpAuthenticator {
|
|||
private AuthScheme authScheme;
|
||||
private HttpContext context;
|
||||
private HttpHost defaultHost;
|
||||
private Credentials credentials;
|
||||
private BasicCredentialsProvider credentialsProvider;
|
||||
private CredentialsProvider credentialsProvider;
|
||||
private Lookup<AuthSchemeProvider> authSchemeRegistry;
|
||||
private AuthCache authCache;
|
||||
private HttpAuthenticator httpAuthenticator;
|
||||
|
@ -78,14 +77,12 @@ public class TestHttpAuthenticator {
|
|||
public void setUp() throws Exception {
|
||||
this.authState = new AuthState();
|
||||
this.authScheme = Mockito.mock(AuthScheme.class);
|
||||
Mockito.when(this.authScheme.getSchemeName()).thenReturn("Basic");
|
||||
Mockito.when(this.authScheme.isComplete()).thenReturn(Boolean.TRUE);
|
||||
Mockito.when(this.authScheme.getName()).thenReturn("Basic");
|
||||
Mockito.when(this.authScheme.isChallengeComplete()).thenReturn(Boolean.TRUE);
|
||||
this.context = new BasicHttpContext();
|
||||
this.defaultHost = new HttpHost("localhost", 80);
|
||||
this.context.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, this.defaultHost);
|
||||
this.credentials = Mockito.mock(Credentials.class);
|
||||
this.credentialsProvider = new BasicCredentialsProvider();
|
||||
this.credentialsProvider.setCredentials(AuthScope.ANY, this.credentials);
|
||||
this.credentialsProvider = Mockito.mock(CredentialsProvider.class);
|
||||
this.context.setAttribute(HttpClientContext.CREDS_PROVIDER, this.credentialsProvider);
|
||||
this.authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create()
|
||||
.register("basic", new BasicSchemeFactory())
|
||||
|
@ -111,7 +108,7 @@ public class TestHttpAuthenticator {
|
|||
final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
|
||||
response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=test");
|
||||
|
||||
this.authState.update(this.authScheme, this.credentials);
|
||||
this.authState.update(this.authScheme);
|
||||
this.authState.setState(AuthProtocolState.SUCCESS);
|
||||
|
||||
Assert.assertTrue(this.httpAuthenticator.isChallenged(
|
||||
|
@ -132,7 +129,7 @@ public class TestHttpAuthenticator {
|
|||
@Test
|
||||
public void testAuthenticationNotRequestedSuccess1() throws Exception {
|
||||
final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
this.authState.update(this.authScheme, this.credentials);
|
||||
this.authState.update(this.authScheme);
|
||||
this.authState.setState(AuthProtocolState.CHALLENGED);
|
||||
|
||||
Assert.assertFalse(this.httpAuthenticator.isChallenged(
|
||||
|
@ -145,7 +142,7 @@ public class TestHttpAuthenticator {
|
|||
@Test
|
||||
public void testAuthenticationNotRequestedSuccess2() throws Exception {
|
||||
final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
this.authState.update(this.authScheme, this.credentials);
|
||||
this.authState.update(this.authScheme);
|
||||
this.authState.setState(AuthProtocolState.HANDSHAKE);
|
||||
|
||||
Assert.assertFalse(this.httpAuthenticator.isChallenged(
|
||||
|
@ -163,20 +160,47 @@ public class TestHttpAuthenticator {
|
|||
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "Digest realm=\"realm1\", nonce=\"1234\""));
|
||||
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "whatever realm=\"realm1\", stuff=\"1234\""));
|
||||
|
||||
final Credentials credentials = new UsernamePasswordCredentials("user:pass");
|
||||
Mockito.when(this.credentialsProvider.getCredentials(Mockito.<AuthScope>any())).thenReturn(credentials);
|
||||
|
||||
final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
|
||||
|
||||
Assert.assertTrue(this.httpAuthenticator.prepareAuthResponse(
|
||||
host, ChallengeType.TARGET, response, authStrategy, this.authState, this.context));
|
||||
Assert.assertEquals(AuthProtocolState.CHALLENGED, this.authState.getState());
|
||||
|
||||
final Queue<AuthOption> options = this.authState.getAuthOptions();
|
||||
final Queue<AuthScheme> options = this.authState.getAuthOptions();
|
||||
Assert.assertNotNull(options);
|
||||
final AuthOption option1 = options.poll();
|
||||
Assert.assertNotNull(option1);
|
||||
Assert.assertEquals("digest", option1.getAuthScheme().getSchemeName());
|
||||
final AuthOption option2 = options.poll();
|
||||
Assert.assertNotNull(option2);
|
||||
Assert.assertEquals("basic", option2.getAuthScheme().getSchemeName());
|
||||
final AuthScheme authScheme1 = options.poll();
|
||||
Assert.assertNotNull(authScheme1);
|
||||
Assert.assertEquals("digest", authScheme1.getName());
|
||||
final AuthScheme authScheme2 = options.poll();
|
||||
Assert.assertNotNull(authScheme2);
|
||||
Assert.assertEquals("basic", authScheme2.getName());
|
||||
Assert.assertNull(options.poll());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthenticationCredentialsForBasic() throws Exception {
|
||||
final HttpHost host = new HttpHost("somehost", 80);
|
||||
final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
|
||||
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"test\""));
|
||||
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "Digest realm=\"realm1\", nonce=\"1234\""));
|
||||
|
||||
final Credentials credentials = new UsernamePasswordCredentials("user:pass");
|
||||
Mockito.when(this.credentialsProvider.getCredentials(new AuthScope(host, "test", "basic"))).thenReturn(credentials);
|
||||
|
||||
final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
|
||||
|
||||
Assert.assertTrue(this.httpAuthenticator.prepareAuthResponse(
|
||||
host, ChallengeType.TARGET, response, authStrategy, this.authState, this.context));
|
||||
Assert.assertEquals(AuthProtocolState.CHALLENGED, this.authState.getState());
|
||||
|
||||
final Queue<AuthScheme> options = this.authState.getAuthOptions();
|
||||
Assert.assertNotNull(options);
|
||||
final AuthScheme authScheme1 = options.poll();
|
||||
Assert.assertNotNull(authScheme1);
|
||||
Assert.assertEquals("basic", authScheme1.getName());
|
||||
Assert.assertNull(options.poll());
|
||||
}
|
||||
|
||||
|
@ -211,8 +235,6 @@ public class TestHttpAuthenticator {
|
|||
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"test\""));
|
||||
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "Digest realm=\"realm1\", nonce=\"1234\""));
|
||||
|
||||
this.credentialsProvider.clear();
|
||||
|
||||
final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
|
||||
|
||||
Assert.assertFalse(this.httpAuthenticator.prepareAuthResponse(
|
||||
|
@ -227,7 +249,7 @@ public class TestHttpAuthenticator {
|
|||
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "Digest realm=\"realm1\", nonce=\"1234\""));
|
||||
|
||||
this.authState.setState(AuthProtocolState.CHALLENGED);
|
||||
this.authState.update(this.authScheme, this.credentials);
|
||||
this.authState.update(this.authScheme);
|
||||
|
||||
final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
|
||||
|
||||
|
@ -267,12 +289,11 @@ public class TestHttpAuthenticator {
|
|||
final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
|
||||
|
||||
this.authState.setState(AuthProtocolState.CHALLENGED);
|
||||
this.authState.update(new BasicScheme(), this.credentials);
|
||||
this.authState.update(new BasicScheme());
|
||||
|
||||
Assert.assertFalse(this.httpAuthenticator.prepareAuthResponse(
|
||||
host, ChallengeType.TARGET, response, authStrategy, this.authState, this.context));
|
||||
Assert.assertEquals(AuthProtocolState.FAILURE, this.authState.getState());
|
||||
Assert.assertNull(this.authState.getCredentials());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -286,7 +307,7 @@ public class TestHttpAuthenticator {
|
|||
final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
|
||||
|
||||
this.authState.setState(AuthProtocolState.CHALLENGED);
|
||||
this.authState.update(new DigestScheme(), this.credentials);
|
||||
this.authState.update(new DigestScheme());
|
||||
|
||||
Assert.assertTrue(this.httpAuthenticator.prepareAuthResponse(
|
||||
host, ChallengeType.TARGET, response, authStrategy, this.authState, this.context));
|
||||
|
@ -301,20 +322,23 @@ public class TestHttpAuthenticator {
|
|||
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "Digest realm=\"realm1\", nonce=\"1234\""));
|
||||
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "whatever realm=\"realm1\", stuff=\"1234\""));
|
||||
|
||||
final Credentials credentials = new UsernamePasswordCredentials("user:pass");
|
||||
Mockito.when(this.credentialsProvider.getCredentials(new AuthScope(host, "realm1", "digest"))).thenReturn(credentials);
|
||||
|
||||
final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
|
||||
|
||||
this.authState.setState(AuthProtocolState.CHALLENGED);
|
||||
this.authState.update(new BasicScheme(), this.credentials);
|
||||
this.authState.update(new BasicScheme());
|
||||
|
||||
Assert.assertTrue(this.httpAuthenticator.prepareAuthResponse(
|
||||
host, ChallengeType.TARGET, response, authStrategy, this.authState, this.context));
|
||||
Assert.assertEquals(AuthProtocolState.CHALLENGED, this.authState.getState());
|
||||
|
||||
final Queue<AuthOption> options = this.authState.getAuthOptions();
|
||||
final Queue<AuthScheme> options = this.authState.getAuthOptions();
|
||||
Assert.assertNotNull(options);
|
||||
final AuthOption option1 = options.poll();
|
||||
Assert.assertNotNull(option1);
|
||||
Assert.assertEquals("digest", option1.getAuthScheme().getSchemeName());
|
||||
final AuthScheme authScheme1 = options.poll();
|
||||
Assert.assertNotNull(authScheme1);
|
||||
Assert.assertEquals("digest", authScheme1.getName());
|
||||
Assert.assertNull(options.poll());
|
||||
}
|
||||
|
||||
|
@ -333,21 +357,20 @@ public class TestHttpAuthenticator {
|
|||
|
||||
Assert.assertEquals(AuthProtocolState.UNCHALLENGED, this.authState.getState());
|
||||
Assert.assertNull(this.authState.getAuthScheme());
|
||||
Assert.assertNull(this.authState.getCredentials());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthFailureState() throws Exception {
|
||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||
this.authState.setState(AuthProtocolState.FAILURE);
|
||||
this.authState.update(this.authScheme, this.credentials);
|
||||
this.authState.update(this.authScheme);
|
||||
|
||||
this.httpAuthenticator.addAuthResponse(request, authState, context);
|
||||
this.httpAuthenticator.addAuthResponse(defaultHost, ChallengeType.TARGET, request, authState, context);
|
||||
|
||||
Assert.assertFalse(request.containsHeader(HttpHeaders.AUTHORIZATION));
|
||||
|
||||
Mockito.verify(this.authScheme, Mockito.never()).authenticate(
|
||||
Mockito.any(Credentials.class),
|
||||
Mockito.verify(this.authScheme, Mockito.never()).generateAuthResponse(
|
||||
Mockito.eq(defaultHost),
|
||||
Mockito.any(HttpRequest.class),
|
||||
Mockito.any(HttpContext.class));
|
||||
}
|
||||
|
@ -356,42 +379,37 @@ public class TestHttpAuthenticator {
|
|||
public void testAuthChallengeStateNoOption() throws Exception {
|
||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||
this.authState.setState(AuthProtocolState.CHALLENGED);
|
||||
this.authState.update(this.authScheme, this.credentials);
|
||||
this.authState.update(this.authScheme);
|
||||
|
||||
Mockito.when(this.authScheme.authenticate(
|
||||
Mockito.any(Credentials.class),
|
||||
Mockito.when(this.authScheme.generateAuthResponse(
|
||||
Mockito.eq(defaultHost),
|
||||
Mockito.any(HttpRequest.class),
|
||||
Mockito.any(HttpContext.class))).thenReturn(new BasicHeader(HttpHeaders.AUTHORIZATION, "stuff"));
|
||||
Mockito.any(HttpContext.class))).thenReturn("stuff");
|
||||
|
||||
this.httpAuthenticator.addAuthResponse(request, authState, context);
|
||||
this.httpAuthenticator.addAuthResponse(defaultHost, ChallengeType.TARGET, request, authState, context);
|
||||
|
||||
Assert.assertTrue(request.containsHeader(HttpHeaders.AUTHORIZATION));
|
||||
|
||||
Mockito.verify(this.authScheme).authenticate(this.credentials, request, this.context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthChallengeStateOneOptions() throws Exception {
|
||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||
this.authState.setState(AuthProtocolState.CHALLENGED);
|
||||
final LinkedList<AuthOption> authOptions = new LinkedList<>();
|
||||
authOptions.add(new AuthOption(this.authScheme, this.credentials));
|
||||
final LinkedList<AuthScheme> authOptions = new LinkedList<>();
|
||||
authOptions.add(this.authScheme);
|
||||
this.authState.update(authOptions);
|
||||
|
||||
Mockito.when(this.authScheme.authenticate(
|
||||
Mockito.any(Credentials.class),
|
||||
Mockito.when(this.authScheme.generateAuthResponse(
|
||||
Mockito.eq(defaultHost),
|
||||
Mockito.any(HttpRequest.class),
|
||||
Mockito.any(HttpContext.class))).thenReturn(new BasicHeader(HttpHeaders.AUTHORIZATION, "stuff"));
|
||||
Mockito.any(HttpContext.class))).thenReturn("stuff");
|
||||
|
||||
this.httpAuthenticator.addAuthResponse(request, authState, context);
|
||||
this.httpAuthenticator.addAuthResponse(defaultHost, ChallengeType.TARGET, request, authState, context);
|
||||
|
||||
Assert.assertSame(this.authScheme, this.authState.getAuthScheme());
|
||||
Assert.assertSame(this.credentials, this.authState.getCredentials());
|
||||
Assert.assertNull(this.authState.getAuthOptions());
|
||||
|
||||
Assert.assertTrue(request.containsHeader(HttpHeaders.AUTHORIZATION));
|
||||
|
||||
Mockito.verify(this.authScheme).authenticate(this.credentials, request, this.context);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -399,74 +417,67 @@ public class TestHttpAuthenticator {
|
|||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||
this.authState.setState(AuthProtocolState.CHALLENGED);
|
||||
|
||||
final LinkedList<AuthOption> authOptions = new LinkedList<>();
|
||||
final LinkedList<AuthScheme> authOptions = new LinkedList<>();
|
||||
final AuthScheme authScheme1 = Mockito.mock(AuthScheme.class);
|
||||
Mockito.doThrow(new AuthenticationException()).when(authScheme1).authenticate(
|
||||
Mockito.any(Credentials.class),
|
||||
Mockito.doThrow(new AuthenticationException()).when(authScheme1).generateAuthResponse(
|
||||
Mockito.eq(defaultHost),
|
||||
Mockito.any(HttpRequest.class),
|
||||
Mockito.any(HttpContext.class));
|
||||
final AuthScheme authScheme2 = Mockito.mock(AuthScheme.class);
|
||||
Mockito.when(authScheme2.authenticate(
|
||||
Mockito.any(Credentials.class),
|
||||
Mockito.when(authScheme2.generateAuthResponse(
|
||||
Mockito.eq(defaultHost),
|
||||
Mockito.any(HttpRequest.class),
|
||||
Mockito.any(HttpContext.class))).thenReturn(new BasicHeader(HttpHeaders.AUTHORIZATION, "stuff"));
|
||||
authOptions.add(new AuthOption(authScheme1, this.credentials));
|
||||
authOptions.add(new AuthOption(authScheme2, this.credentials));
|
||||
Mockito.any(HttpContext.class))).thenReturn("stuff");
|
||||
authOptions.add(authScheme1);
|
||||
authOptions.add(authScheme2);
|
||||
this.authState.update(authOptions);
|
||||
|
||||
this.httpAuthenticator.addAuthResponse(request, authState, context);
|
||||
this.httpAuthenticator.addAuthResponse(defaultHost, ChallengeType.TARGET, request, authState, context);
|
||||
|
||||
Assert.assertSame(authScheme2, this.authState.getAuthScheme());
|
||||
Assert.assertSame(this.credentials, this.authState.getCredentials());
|
||||
Assert.assertNull(this.authState.getAuthOptions());
|
||||
|
||||
Assert.assertTrue(request.containsHeader(HttpHeaders.AUTHORIZATION));
|
||||
|
||||
Mockito.verify(authScheme1, Mockito.times(1)).authenticate(this.credentials, request, this.context);
|
||||
Mockito.verify(authScheme2, Mockito.times(1)).authenticate(this.credentials, request, this.context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthSuccess() throws Exception {
|
||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||
this.authState.setState(AuthProtocolState.SUCCESS);
|
||||
this.authState.update(this.authScheme, this.credentials);
|
||||
this.authState.update(this.authScheme);
|
||||
|
||||
Mockito.when(this.authScheme.isConnectionBased()).thenReturn(Boolean.FALSE);
|
||||
Mockito.when(this.authScheme.authenticate(
|
||||
Mockito.any(Credentials.class),
|
||||
Mockito.when(this.authScheme.generateAuthResponse(
|
||||
Mockito.eq(defaultHost),
|
||||
Mockito.any(HttpRequest.class),
|
||||
Mockito.any(HttpContext.class))).thenReturn(new BasicHeader(HttpHeaders.AUTHORIZATION, "stuff"));
|
||||
Mockito.any(HttpContext.class))).thenReturn("stuff");
|
||||
|
||||
this.httpAuthenticator.addAuthResponse(request, authState, context);
|
||||
this.httpAuthenticator.addAuthResponse(defaultHost, ChallengeType.TARGET, request, authState, context);
|
||||
|
||||
Assert.assertSame(this.authScheme, this.authState.getAuthScheme());
|
||||
Assert.assertSame(this.credentials, this.authState.getCredentials());
|
||||
Assert.assertNull(this.authState.getAuthOptions());
|
||||
|
||||
Assert.assertTrue(request.containsHeader(HttpHeaders.AUTHORIZATION));
|
||||
|
||||
Mockito.verify(this.authScheme).authenticate(this.credentials, request, this.context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthSuccessConnectionBased() throws Exception {
|
||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||
this.authState.setState(AuthProtocolState.SUCCESS);
|
||||
this.authState.update(this.authScheme, this.credentials);
|
||||
this.authState.update(this.authScheme);
|
||||
|
||||
Mockito.when(this.authScheme.isConnectionBased()).thenReturn(Boolean.TRUE);
|
||||
Mockito.when(this.authScheme.authenticate(
|
||||
Mockito.any(Credentials.class),
|
||||
Mockito.when(this.authScheme.generateAuthResponse(
|
||||
Mockito.eq(defaultHost),
|
||||
Mockito.any(HttpRequest.class),
|
||||
Mockito.any(HttpContext.class))).thenReturn(new BasicHeader(HttpHeaders.AUTHORIZATION, "stuff"));
|
||||
Mockito.any(HttpContext.class))).thenReturn("stuff");
|
||||
|
||||
this.httpAuthenticator.addAuthResponse(request, authState, context);
|
||||
this.httpAuthenticator.addAuthResponse(defaultHost, ChallengeType.TARGET, request, authState, context);
|
||||
|
||||
Assert.assertFalse(request.containsHeader(HttpHeaders.AUTHORIZATION));
|
||||
|
||||
Mockito.verify(this.authScheme, Mockito.never()).authenticate(
|
||||
Mockito.any(Credentials.class),
|
||||
Mockito.verify(this.authScheme, Mockito.never()).generateAuthResponse(
|
||||
Mockito.eq(defaultHost),
|
||||
Mockito.any(HttpRequest.class),
|
||||
Mockito.any(HttpContext.class));
|
||||
}
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.HttpRequest;
|
||||
import org.apache.http.auth.AuthChallenge;
|
||||
import org.apache.http.auth.AuthenticationException;
|
||||
import org.apache.http.auth.ChallengeType;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.auth.MalformedChallengeException;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TestNonStandardHttpScheme {
|
||||
|
||||
static class TestAuthScheme extends NonStandardAuthScheme {
|
||||
|
||||
@Override
|
||||
public void processChallenge(
|
||||
final ChallengeType challengeType, final AuthChallenge authChallenge) throws MalformedChallengeException {
|
||||
update(challengeType, authChallenge);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Header authenticate(
|
||||
final Credentials credentials,
|
||||
final HttpRequest request,
|
||||
final HttpContext context) throws AuthenticationException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchemeName() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isComplete() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnectionBased() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessChallenge() throws Exception {
|
||||
final TestAuthScheme authscheme = new TestAuthScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, new AuthChallenge("Test", "this_and_that", null));
|
||||
|
||||
Assert.assertEquals("test", authscheme.getSchemeName());
|
||||
Assert.assertEquals("test(TARGET) this_and_that", authscheme.toString());
|
||||
Assert.assertEquals("this_and_that", authscheme.getChallenge());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.Arrays;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.auth.AuthChallenge;
|
||||
import org.apache.http.auth.AuthenticationException;
|
||||
import org.apache.http.auth.ChallengeType;
|
||||
import org.apache.http.auth.Credentials;
|
||||
import org.apache.http.auth.MalformedChallengeException;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TestStandardHttpScheme {
|
||||
|
||||
static class TestAuthScheme extends StandardAuthScheme {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public void processChallenge(
|
||||
final ChallengeType challengeType, final AuthChallenge authChallenge) throws MalformedChallengeException {
|
||||
update(challengeType, authChallenge);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Header authenticate(
|
||||
final Credentials credentials,
|
||||
final HttpRequest request,
|
||||
final HttpContext context) throws AuthenticationException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchemeName() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isComplete() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnectionBased() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessChallenge() throws Exception {
|
||||
final TestAuthScheme authscheme = new TestAuthScheme();
|
||||
authscheme.processChallenge(ChallengeType.TARGET, new AuthChallenge("Test", null, Arrays.asList(
|
||||
new BasicNameValuePair("realm", "realm1"), new BasicNameValuePair("this", "blah"))));
|
||||
|
||||
Assert.assertEquals("test", authscheme.getSchemeName());
|
||||
Assert.assertEquals("test(TARGET) {realm=realm1, this=blah}", authscheme.toString());
|
||||
Assert.assertEquals("realm1", authscheme.getParameter("realm"));
|
||||
Assert.assertEquals(null, authscheme.getParameter("test"));
|
||||
Assert.assertEquals("blah", authscheme.getParameter("this"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -588,14 +588,12 @@ public class TestClientAuthentication extends LocalServerTestBase {
|
|||
|
||||
final HttpHost target = start();
|
||||
|
||||
final BasicScheme basicScheme = new BasicScheme();
|
||||
basicScheme.initPreemptive(new UsernamePasswordCredentials("test", "test"));
|
||||
final HttpClientContext context = HttpClientContext.create();
|
||||
final AuthCache authCache = new BasicAuthCache();
|
||||
authCache.put(target, new BasicScheme());
|
||||
authCache.put(target, basicScheme);
|
||||
context.setAuthCache(authCache);
|
||||
final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
|
||||
credsProvider.setCredentials(AuthScope.ANY,
|
||||
new UsernamePasswordCredentials("test", "test"));
|
||||
context.setCredentialsProvider(credsProvider);
|
||||
|
||||
final HttpGet httpget = new HttpGet("/");
|
||||
final HttpResponse response1 = this.httpclient.execute(target, httpget, context);
|
||||
|
|
|
@ -153,7 +153,7 @@ public class TestClientReauthentication extends LocalServerTestBase {
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public String getSchemeName() {
|
||||
public String getName() {
|
||||
return "MyBasic";
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,6 @@ import org.apache.http.auth.AuthScheme;
|
|||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.AuthState;
|
||||
import org.apache.http.auth.ChallengeType;
|
||||
import org.apache.http.auth.NTCredentials;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.client.AuthenticationStrategy;
|
||||
import org.apache.http.client.NonRepeatableRequestException;
|
||||
|
@ -442,7 +441,7 @@ public class TestMainClientExec {
|
|||
|
||||
final AuthState proxyAuthState = new AuthState();
|
||||
proxyAuthState.setState(AuthProtocolState.SUCCESS);
|
||||
proxyAuthState.update(new NTLMScheme(), new NTCredentials("user:pass"));
|
||||
proxyAuthState.update(new NTLMScheme());
|
||||
|
||||
final HttpClientContext context = new HttpClientContext();
|
||||
context.setAttribute(HttpClientContext.PROXY_AUTH_STATE, proxyAuthState);
|
||||
|
@ -475,7 +474,6 @@ public class TestMainClientExec {
|
|||
Assert.assertNotNull(finalResponse);
|
||||
Assert.assertEquals(200, finalResponse.getStatusLine().getStatusCode());
|
||||
Assert.assertNull(proxyAuthState.getAuthScheme());
|
||||
Assert.assertNull(proxyAuthState.getCredentials());
|
||||
}
|
||||
|
||||
@Test(expected = NonRepeatableRequestException.class)
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
*/
|
||||
package org.apache.http.impl.execchain;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpException;
|
||||
|
@ -35,8 +39,6 @@ import org.apache.http.HttpResponse;
|
|||
import org.apache.http.ProtocolException;
|
||||
import org.apache.http.auth.AuthProtocolState;
|
||||
import org.apache.http.auth.AuthState;
|
||||
import org.apache.http.auth.NTCredentials;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.client.RedirectException;
|
||||
import org.apache.http.client.RedirectStrategy;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
|
@ -60,10 +62,6 @@ import org.mockito.Mock;
|
|||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings({"boxing","static-access"}) // test code
|
||||
public class TestRedirectExec {
|
||||
|
||||
|
@ -240,10 +238,10 @@ public class TestRedirectExec {
|
|||
|
||||
final AuthState targetAuthState = new AuthState();
|
||||
targetAuthState.setState(AuthProtocolState.SUCCESS);
|
||||
targetAuthState.update(new BasicScheme(), new UsernamePasswordCredentials("user:pass"));
|
||||
targetAuthState.update(new BasicScheme());
|
||||
final AuthState proxyAuthState = new AuthState();
|
||||
proxyAuthState.setState(AuthProtocolState.SUCCESS);
|
||||
proxyAuthState.update(new NTLMScheme(), new NTCredentials("user:pass"));
|
||||
proxyAuthState.update(new NTLMScheme());
|
||||
context.setAttribute(HttpClientContext.TARGET_AUTH_STATE, targetAuthState);
|
||||
context.setAttribute(HttpClientContext.PROXY_AUTH_STATE, proxyAuthState);
|
||||
|
||||
|
|
|
@ -546,7 +546,7 @@ HttpRoutePlanner routePlanner = new HttpRoutePlanner() {
|
|||
HttpRequest request,
|
||||
HttpContext context) throws HttpException {
|
||||
return new HttpRoute(target, null, new HttpHost("someproxy", 8080),
|
||||
"https".equalsIgnoreCase(target.getSchemeName()));
|
||||
"https".equalsIgnoreCase(target.getName()));
|
||||
}
|
||||
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue