mirror of
https://github.com/apache/httpcomponents-client.git
synced 2025-02-08 19:15:16 +00:00
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 @@
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.KeyManagementException;
|
import java.security.KeyManagementException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
|
|
||||||
import org.apache.http.HttpHost;
|
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.AuthScope;
|
||||||
import org.apache.http.auth.ChallengeType;
|
|
||||||
import org.apache.http.auth.Credentials;
|
import org.apache.http.auth.Credentials;
|
||||||
import org.apache.http.auth.MalformedChallengeException;
|
|
||||||
import org.apache.http.auth.NTCredentials;
|
import org.apache.http.auth.NTCredentials;
|
||||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||||
import org.apache.http.client.AuthCache;
|
import org.apache.http.client.AuthCache;
|
||||||
@ -151,12 +146,14 @@ public Executor auth(final String host, final Credentials creds) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Executor authPreemptive(final HttpHost host) {
|
public Executor authPreemptive(final HttpHost host) {
|
||||||
final BasicScheme basicScheme = new BasicScheme();
|
if (this.credentialsStore != null) {
|
||||||
try {
|
final Credentials credentials = this.credentialsStore.getCredentials(new AuthScope(host));
|
||||||
basicScheme.processChallenge(ChallengeType.TARGET, new AuthChallenge("basic", null, Collections.<NameValuePair>emptyList()));
|
if (credentials == null) {
|
||||||
} catch (final MalformedChallengeException ignore) {
|
final BasicScheme basicScheme = new BasicScheme();
|
||||||
|
basicScheme.initPreemptive(credentials);
|
||||||
|
this.authCache.put(host, basicScheme);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.authCache.put(host, basicScheme);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,12 +165,14 @@ public Executor authPreemptive(final String host) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Executor authPreemptiveProxy(final HttpHost proxy) {
|
public Executor authPreemptiveProxy(final HttpHost proxy) {
|
||||||
final BasicScheme basicScheme = new BasicScheme();
|
if (this.credentialsStore != null) {
|
||||||
try {
|
final Credentials credentials = this.credentialsStore.getCredentials(new AuthScope(proxy));
|
||||||
basicScheme.processChallenge(ChallengeType.PROXY, new AuthChallenge("basic", null, Collections.<NameValuePair>emptyList()));
|
if (credentials == null) {
|
||||||
} catch (final MalformedChallengeException ignore) {
|
final BasicScheme basicScheme = new BasicScheme();
|
||||||
|
basicScheme.initPreemptive(credentials);
|
||||||
|
this.authCache.put(proxy, basicScheme);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.authCache.put(proxy, basicScheme);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,10 +65,10 @@ public interface HttpCacheStorage {
|
|||||||
void removeEntry(String key) throws IOException;
|
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.
|
* entry under a given key.
|
||||||
* @param key indicates which entry to modify
|
* @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
|
* {@link HttpCacheUpdateCallback} for details, but roughly the
|
||||||
* callback expects to be handed the current entry and will return
|
* callback expects to be handed the current entry and will return
|
||||||
* the new value for the entry.
|
* the new value for the entry.
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Signals that {@link HttpCacheStorage} encountered an error performing an
|
* Signals that {@link HttpCacheStorage} encountered an error performing an
|
||||||
* update operation.
|
* processChallenge operation.
|
||||||
*
|
*
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
*/
|
*/
|
||||||
|
@ -165,7 +165,7 @@ public HttpCacheEntry update(final HttpCacheEntry existing) throws IOException {
|
|||||||
try {
|
try {
|
||||||
storage.updateEntry(parentURI, callback);
|
storage.updateEntry(parentURI, callback);
|
||||||
} catch (final HttpCacheUpdateException e) {
|
} catch (final HttpCacheUpdateException e) {
|
||||||
log.warn("Could not update key [" + parentURI + "]", e);
|
log.warn("Could not processChallenge key [" + parentURI + "]", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +189,7 @@ public HttpCacheEntry update(final HttpCacheEntry existing)
|
|||||||
try {
|
try {
|
||||||
storage.updateEntry(parentCacheKey, callback);
|
storage.updateEntry(parentCacheKey, callback);
|
||||||
} catch (final HttpCacheUpdateException e) {
|
} 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;
|
public final static int DEFAULT_MAX_CACHE_ENTRIES = 1000;
|
||||||
|
|
||||||
/** Default setting for the number of retries on a failed
|
/** Default setting for the number of retries on a failed
|
||||||
* cache update
|
* cache processChallenge
|
||||||
*/
|
*/
|
||||||
public final static int DEFAULT_MAX_UPDATE_RETRIES = 1;
|
public final static int DEFAULT_MAX_UPDATE_RETRIES = 1;
|
||||||
|
|
||||||
@ -234,7 +234,7 @@ public int getMaxCacheEntries() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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(){
|
public int getMaxUpdateRetries(){
|
||||||
return maxUpdateRetries;
|
return maxUpdateRetries;
|
||||||
@ -400,7 +400,7 @@ public Builder setMaxCacheEntries(final int maxCacheEntries) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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) {
|
public Builder setMaxUpdateRetries(final int maxUpdateRetries) {
|
||||||
this.maxUpdateRetries = maxUpdateRetries;
|
this.maxUpdateRetries = maxUpdateRetries;
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
/**
|
/**
|
||||||
* Update a {@link HttpCacheEntry} with new or updated information based on the latest
|
* 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
|
* 304 status response from the Server. Use the {@link HttpResponse} to perform
|
||||||
* the update.
|
* the processChallenge.
|
||||||
*
|
*
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
*/
|
*/
|
||||||
|
@ -712,7 +712,7 @@ private HttpCacheEntry getUpdatedVariantEntry(
|
|||||||
responseEntry = responseCache.updateVariantCacheEntry(target, conditionalRequest,
|
responseEntry = responseCache.updateVariantCacheEntry(target, conditionalRequest,
|
||||||
matchedEntry, backendResponse, requestDate, responseDate, matchingVariant.getCacheKey());
|
matchedEntry, backendResponse, requestDate, responseDate, matchingVariant.getCacheKey());
|
||||||
} catch (final IOException ioe) {
|
} catch (final IOException ioe) {
|
||||||
log.warn("Could not update cache entry", ioe);
|
log.warn("Could not processChallenge cache entry", ioe);
|
||||||
} finally {
|
} finally {
|
||||||
backendResponse.close();
|
backendResponse.close();
|
||||||
}
|
}
|
||||||
@ -726,7 +726,7 @@ private void tryToUpdateVariantMap(
|
|||||||
try {
|
try {
|
||||||
responseCache.reuseVariantEntryFor(target, request, matchingVariant);
|
responseCache.reuseVariantEntryFor(target, request, matchingVariant);
|
||||||
} catch (final IOException ioe) {
|
} 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 @@ private void updateValue(final String identifier) {
|
|||||||
*
|
*
|
||||||
* In case there is a lot of contention on that identifier, a thread
|
* 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
|
* 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++) {
|
for (int i = 0; i < MAX_UPDATE_TRIES; i++) {
|
||||||
final FailureCacheValue oldValue = storage.get(identifier);
|
final FailureCacheValue oldValue = storage.get(identifier);
|
||||||
|
@ -159,7 +159,7 @@ HttpCacheEntry updateVariantCacheEntry(HttpHost target, HttpRequest request,
|
|||||||
* @param target host of the upstream client request
|
* @param target host of the upstream client request
|
||||||
* @param req request sent by upstream client
|
* @param req request sent by upstream client
|
||||||
* @param variant variant cache entry to reuse
|
* @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,
|
void reuseVariantEntryFor(HttpHost target, final HttpRequest req,
|
||||||
final Variant variant) throws IOException;
|
final Variant variant) throws IOException;
|
||||||
|
@ -156,6 +156,6 @@ public synchronized void updateEntry(final String key, final HttpCacheUpdateCall
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}while(numRetries <= maxUpdateRetries);
|
}while(numRetries <= maxUpdateRetries);
|
||||||
throw new HttpCacheUpdateException("Failed to update");
|
throw new HttpCacheUpdateException("Failed to processChallenge");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,6 +268,6 @@ public void updateEntry(final String url, final HttpCacheUpdateCallback callback
|
|||||||
}
|
}
|
||||||
} while (numRetries <= maxUpdateRetries);
|
} while (numRetries <= maxUpdateRetries);
|
||||||
|
|
||||||
throw new HttpCacheUpdateException("Failed to update");
|
throw new HttpCacheUpdateException("Failed to processChallenge");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1208,7 +1208,7 @@ public void testSendsAllVariantEtagsInConditionalRequest()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* "If the entity-tag of the new response matches that of an existing
|
/* "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
|
* of the existing entry, and the result MUST be returned to the
|
||||||
* client."
|
* client."
|
||||||
*
|
*
|
||||||
|
@ -2198,8 +2198,8 @@ public void testNotModifiedOfNonCachedEntityShouldRevalidateWithUnconditionalGET
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "If a cache uses a received 304 response to update a cache entry, the
|
* "If a cache uses a received 304 response to processChallenge a cache entry, the
|
||||||
* cache MUST update the entry to reflect any new field values given in the
|
* cache MUST processChallenge the entry to reflect any new field values given in the
|
||||||
* response.
|
* response.
|
||||||
*
|
*
|
||||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5
|
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5
|
||||||
@ -4539,7 +4539,7 @@ public void testCannotServeFromCacheForVaryStar() throws Exception {
|
|||||||
* the ETag header field in its 304 (Not Modified) response to
|
* the ETag header field in its 304 (Not Modified) response to
|
||||||
* tell the cache which entry is appropriate. If the entity-tag of
|
* tell the cache which entry is appropriate. If the entity-tag of
|
||||||
* the new response matches that of an existing entry, the new
|
* 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.
|
* existing entry, and the result MUST be returned to the client.
|
||||||
*
|
*
|
||||||
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6
|
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6
|
||||||
|
@ -168,7 +168,7 @@ public HttpCacheEntry update(final HttpCacheEntry old){
|
|||||||
when(mockCache.get(key)).thenReturn(existingElement);
|
when(mockCache.get(key)).thenReturn(existingElement);
|
||||||
when(mockSerializer.readFrom(isA(InputStream.class))).thenReturn(existingValue);
|
when(mockSerializer.readFrom(isA(InputStream.class))).thenReturn(existingValue);
|
||||||
|
|
||||||
// update
|
// processChallenge
|
||||||
mockSerializer.writeTo(same(updatedValue), isA(OutputStream.class));
|
mockSerializer.writeTo(same(updatedValue), isA(OutputStream.class));
|
||||||
when(mockCache.replace(same(existingElement), isA(Element.class))).thenReturn(true);
|
when(mockCache.replace(same(existingElement), isA(Element.class))).thenReturn(true);
|
||||||
|
|
||||||
@ -231,7 +231,7 @@ public HttpCacheEntry update(final HttpCacheEntry old){
|
|||||||
when(mockCache.get(key)).thenReturn(existingElement);
|
when(mockCache.get(key)).thenReturn(existingElement);
|
||||||
when(mockSerializer.readFrom(isA(InputStream.class))).thenReturn(existingValue);
|
when(mockSerializer.readFrom(isA(InputStream.class))).thenReturn(existingValue);
|
||||||
|
|
||||||
// update but fail
|
// processChallenge but fail
|
||||||
when(mockCache.replace(same(existingElement), isA(Element.class))).thenReturn(false);
|
when(mockCache.replace(same(existingElement), isA(Element.class))).thenReturn(false);
|
||||||
|
|
||||||
try{
|
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;
|
package org.apache.http.impl.auth.win;
|
||||||
|
|
||||||
|
import java.security.Principal;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
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.HttpHost;
|
||||||
import org.apache.http.HttpRequest;
|
import org.apache.http.HttpRequest;
|
||||||
import org.apache.http.annotation.NotThreadSafe;
|
import org.apache.http.annotation.NotThreadSafe;
|
||||||
import org.apache.http.auth.AuthChallenge;
|
import org.apache.http.auth.AuthChallenge;
|
||||||
|
import org.apache.http.auth.AuthScheme;
|
||||||
import org.apache.http.auth.AuthenticationException;
|
import org.apache.http.auth.AuthenticationException;
|
||||||
import org.apache.http.auth.ChallengeType;
|
import org.apache.http.auth.BasicUserPrincipal;
|
||||||
import org.apache.http.auth.Credentials;
|
import org.apache.http.auth.CredentialsProvider;
|
||||||
import org.apache.http.auth.InvalidCredentialsException;
|
|
||||||
import org.apache.http.auth.MalformedChallengeException;
|
import org.apache.http.auth.MalformedChallengeException;
|
||||||
import org.apache.http.client.config.AuthSchemes;
|
import org.apache.http.client.config.AuthSchemes;
|
||||||
import org.apache.http.client.protocol.HttpClientContext;
|
import org.apache.http.client.protocol.HttpClientContext;
|
||||||
import org.apache.http.conn.routing.RouteInfo;
|
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.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.Secur32;
|
||||||
|
import com.sun.jna.platform.win32.Secur32Util;
|
||||||
import com.sun.jna.platform.win32.Sspi;
|
import com.sun.jna.platform.win32.Sspi;
|
||||||
import com.sun.jna.platform.win32.Sspi.CredHandle;
|
import com.sun.jna.platform.win32.Sspi.CredHandle;
|
||||||
import com.sun.jna.platform.win32.Sspi.CtxtHandle;
|
import com.sun.jna.platform.win32.Sspi.CtxtHandle;
|
||||||
@ -70,7 +69,7 @@
|
|||||||
* @since 4.4
|
* @since 4.4
|
||||||
*/
|
*/
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
public class WindowsNegotiateScheme extends NonStandardAuthScheme {
|
public class WindowsNegotiateScheme implements AuthScheme {
|
||||||
|
|
||||||
private final Log log = LogFactory.getLog(getClass());
|
private final Log log = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
@ -78,6 +77,7 @@ public class WindowsNegotiateScheme extends NonStandardAuthScheme {
|
|||||||
private final String scheme;
|
private final String scheme;
|
||||||
private final String servicePrincipalName;
|
private final String servicePrincipalName;
|
||||||
|
|
||||||
|
private String challenge;
|
||||||
private CredHandle clientCred;
|
private CredHandle clientCred;
|
||||||
private CtxtHandle sspiContext;
|
private CtxtHandle sspiContext;
|
||||||
private boolean continueNeeded;
|
private boolean continueNeeded;
|
||||||
@ -119,7 +119,7 @@ public void finalize() throws Throwable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSchemeName() {
|
public String getName() {
|
||||||
return scheme;
|
return scheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,11 +128,20 @@ public boolean isConnectionBased() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRealm() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processChallenge(
|
public void processChallenge(
|
||||||
final ChallengeType challengeType, final AuthChallenge authChallenge) throws MalformedChallengeException {
|
final AuthChallenge authChallenge,
|
||||||
update(challengeType, authChallenge);
|
final HttpContext context) throws MalformedChallengeException {
|
||||||
final String challenge = getChallenge();
|
Args.notNull(authChallenge, "AuthChallenge");
|
||||||
|
if (authChallenge.getValue() == null) {
|
||||||
|
throw new MalformedChallengeException("Missing auth challenge");
|
||||||
|
}
|
||||||
|
challenge = authChallenge.getValue();
|
||||||
if (challenge.isEmpty()) {
|
if (challenge.isEmpty()) {
|
||||||
if (clientCred != null) {
|
if (clientCred != null) {
|
||||||
dispose(); // run cleanup first before throwing an exception otherwise can leak OS resources
|
dispose(); // run cleanup first before throwing an exception otherwise can leak OS resources
|
||||||
@ -144,24 +153,38 @@ public void processChallenge(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Header authenticate(
|
public boolean isResponseReady(
|
||||||
final Credentials credentials,
|
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 HttpRequest request,
|
||||||
final HttpContext context) throws AuthenticationException {
|
final HttpContext context) throws AuthenticationException {
|
||||||
|
|
||||||
final String challenge = getChallenge();
|
|
||||||
final String response;
|
final String response;
|
||||||
if (clientCred == null) {
|
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
|
// client credentials handle
|
||||||
try {
|
try {
|
||||||
final String username = CurrentWindowsCredentials.getCurrentUsername();
|
final String username = getCurrentUsername();
|
||||||
final TimeStamp lifetime = new TimeStamp();
|
final TimeStamp lifetime = new TimeStamp();
|
||||||
|
|
||||||
clientCred = new CredHandle();
|
clientCred = new CredHandle();
|
||||||
@ -202,18 +225,7 @@ public Header authenticate(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return scheme + " " + response;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void failAuthCleanup() {
|
private void failAuthCleanup() {
|
||||||
@ -281,7 +293,7 @@ String getToken(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isComplete() {
|
public boolean isChallengeComplete() {
|
||||||
return !continueNeeded;
|
return !continueNeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,13 +29,11 @@
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.apache.http.auth.AuthSchemeProvider;
|
import org.apache.http.auth.AuthSchemeProvider;
|
||||||
import org.apache.http.auth.CredentialsProvider;
|
|
||||||
import org.apache.http.client.config.AuthSchemes;
|
import org.apache.http.client.config.AuthSchemes;
|
||||||
import org.apache.http.config.Registry;
|
import org.apache.http.config.Registry;
|
||||||
import org.apache.http.config.RegistryBuilder;
|
import org.apache.http.config.RegistryBuilder;
|
||||||
import org.apache.http.impl.auth.BasicSchemeFactory;
|
import org.apache.http.impl.auth.BasicSchemeFactory;
|
||||||
import org.apache.http.impl.auth.DigestSchemeFactory;
|
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.WindowsNTLMSchemeFactory;
|
||||||
import org.apache.http.impl.auth.win.WindowsNegotiateSchemeFactory;
|
import org.apache.http.impl.auth.win.WindowsNegotiateSchemeFactory;
|
||||||
|
|
||||||
@ -74,9 +72,7 @@ private static HttpClientBuilder createBuilder() {
|
|||||||
.register(AuthSchemes.NTLM, new WindowsNTLMSchemeFactory(null))
|
.register(AuthSchemes.NTLM, new WindowsNTLMSchemeFactory(null))
|
||||||
.register(AuthSchemes.SPNEGO, new WindowsNegotiateSchemeFactory(null))
|
.register(AuthSchemes.SPNEGO, new WindowsNegotiateSchemeFactory(null))
|
||||||
.build();
|
.build();
|
||||||
final CredentialsProvider credsProvider = new WindowsCredentialsProvider(new SystemDefaultCredentialsProvider());
|
|
||||||
return HttpClientBuilder.create()
|
return HttpClientBuilder.create()
|
||||||
.setDefaultCredentialsProvider(credsProvider)
|
|
||||||
.setDefaultAuthSchemeRegistry(authSchemeRegistry);
|
.setDefaultAuthSchemeRegistry(authSchemeRegistry);
|
||||||
} else {
|
} else {
|
||||||
return HttpClientBuilder.create();
|
return HttpClientBuilder.create();
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
import org.apache.http.HttpStatus;
|
import org.apache.http.HttpStatus;
|
||||||
import org.apache.http.auth.AuthScheme;
|
import org.apache.http.auth.AuthScheme;
|
||||||
import org.apache.http.auth.AuthSchemeProvider;
|
import org.apache.http.auth.AuthSchemeProvider;
|
||||||
import org.apache.http.auth.CredentialsProvider;
|
|
||||||
import org.apache.http.client.config.AuthSchemes;
|
import org.apache.http.client.config.AuthSchemes;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
@ -44,7 +43,6 @@
|
|||||||
import org.apache.http.config.RegistryBuilder;
|
import org.apache.http.config.RegistryBuilder;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
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.impl.client.WinHttpClients;
|
||||||
import org.apache.http.localserver.LocalServerTestBase;
|
import org.apache.http.localserver.LocalServerTestBase;
|
||||||
import org.apache.http.protocol.HttpContext;
|
import org.apache.http.protocol.HttpContext;
|
||||||
@ -105,10 +103,7 @@ public AuthScheme create(final HttpContext context) {
|
|||||||
return new WindowsNegotiateSchemeGetTokenFail(AuthSchemes.SPNEGO, "HTTP/example.com");
|
return new WindowsNegotiateSchemeGetTokenFail(AuthSchemes.SPNEGO, "HTTP/example.com");
|
||||||
}
|
}
|
||||||
}).build();
|
}).build();
|
||||||
final CredentialsProvider credsProvider =
|
|
||||||
new WindowsCredentialsProvider(new SystemDefaultCredentialsProvider());
|
|
||||||
final CloseableHttpClient customClient = HttpClientBuilder.create()
|
final CloseableHttpClient customClient = HttpClientBuilder.create()
|
||||||
.setDefaultCredentialsProvider(credsProvider)
|
|
||||||
.setDefaultAuthSchemeRegistry(authSchemeRegistry).build();
|
.setDefaultAuthSchemeRegistry(authSchemeRegistry).build();
|
||||||
|
|
||||||
final HttpHost target = start();
|
final HttpHost target = start();
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
package org.apache.http.examples.client;
|
package org.apache.http.examples.client;
|
||||||
|
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.auth.AuthScope;
|
|
||||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||||
import org.apache.http.client.AuthCache;
|
import org.apache.http.client.AuthCache;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
@ -35,7 +34,6 @@
|
|||||||
import org.apache.http.client.protocol.HttpClientContext;
|
import org.apache.http.client.protocol.HttpClientContext;
|
||||||
import org.apache.http.impl.auth.BasicScheme;
|
import org.apache.http.impl.auth.BasicScheme;
|
||||||
import org.apache.http.impl.client.BasicAuthCache;
|
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.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.impl.client.HttpClients;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
@ -52,18 +50,13 @@ public class ClientPreemptiveBasicAuthentication {
|
|||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
HttpHost target = new HttpHost("localhost", 80, "http");
|
HttpHost target = new HttpHost("localhost", 80, "http");
|
||||||
BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
|
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
|
||||||
credsProvider.setCredentials(
|
|
||||||
new AuthScope(target.getHostName(), target.getPort()),
|
|
||||||
new UsernamePasswordCredentials("username", "password"));
|
|
||||||
try (CloseableHttpClient httpclient = HttpClients.custom()
|
|
||||||
.setDefaultCredentialsProvider(credsProvider).build()) {
|
|
||||||
|
|
||||||
// Create AuthCache instance
|
// Create AuthCache instance
|
||||||
AuthCache authCache = new BasicAuthCache();
|
AuthCache authCache = new BasicAuthCache();
|
||||||
// Generate BASIC scheme object and add it to the local
|
// Generate BASIC scheme object and add it to the local auth cache
|
||||||
// auth cache
|
|
||||||
BasicScheme basicAuth = new BasicScheme();
|
BasicScheme basicAuth = new BasicScheme();
|
||||||
|
basicAuth.initPreemptive(new UsernamePasswordCredentials("username", "password"));
|
||||||
authCache.put(target, basicAuth);
|
authCache.put(target, basicAuth);
|
||||||
|
|
||||||
// Add AuthCache to the execution context
|
// Add AuthCache to the execution context
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
package org.apache.http.examples.client;
|
package org.apache.http.examples.client;
|
||||||
|
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.auth.AuthScope;
|
|
||||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||||
import org.apache.http.client.AuthCache;
|
import org.apache.http.client.AuthCache;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
@ -35,7 +34,6 @@
|
|||||||
import org.apache.http.client.protocol.HttpClientContext;
|
import org.apache.http.client.protocol.HttpClientContext;
|
||||||
import org.apache.http.impl.auth.DigestScheme;
|
import org.apache.http.impl.auth.DigestScheme;
|
||||||
import org.apache.http.impl.client.BasicAuthCache;
|
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.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.impl.client.HttpClients;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
@ -53,23 +51,14 @@ public class ClientPreemptiveDigestAuthentication {
|
|||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
HttpHost target = new HttpHost("localhost", 80, "http");
|
HttpHost target = new HttpHost("localhost", 80, "http");
|
||||||
BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
|
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
|
||||||
credsProvider.setCredentials(
|
|
||||||
new AuthScope(target.getHostName(), target.getPort()),
|
|
||||||
new UsernamePasswordCredentials("username", "password"));
|
|
||||||
try (CloseableHttpClient httpclient = HttpClients.custom()
|
|
||||||
.setDefaultCredentialsProvider(credsProvider)
|
|
||||||
.build()) {
|
|
||||||
|
|
||||||
// Create AuthCache instance
|
// Create AuthCache instance
|
||||||
AuthCache authCache = new BasicAuthCache();
|
AuthCache authCache = new BasicAuthCache();
|
||||||
// Generate DIGEST scheme object, initialize it and add it to the local
|
// Generate DIGEST scheme object, initialize it and add it to the local auth cache
|
||||||
// auth cache
|
|
||||||
DigestScheme digestAuth = new DigestScheme();
|
DigestScheme digestAuth = new DigestScheme();
|
||||||
// Suppose we already know the realm name
|
// Suppose we already know the realm name and the expected nonce value
|
||||||
digestAuth.overrideParamter("realm", "some realm");
|
digestAuth.initPreemptive(new UsernamePasswordCredentials("username", "password"), "whatever", "realm");
|
||||||
// Suppose we already know the expected nonce value
|
|
||||||
digestAuth.overrideParamter("nonce", "whatever");
|
|
||||||
authCache.put(target, digestAuth);
|
authCache.put(target, digestAuth);
|
||||||
|
|
||||||
// Add AuthCache to the execution context
|
// 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;
|
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.HttpRequest;
|
||||||
import org.apache.http.protocol.HttpContext;
|
import org.apache.http.protocol.HttpContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface represents an abstract challenge-response oriented
|
* This interface represents an abstract challenge-response oriented authentication scheme.
|
||||||
* authentication scheme.
|
|
||||||
* <p>
|
* <p>
|
||||||
* Authentication schemes may be stateful involving a series of
|
* Authentication schemes can be either request or connection based. The former are
|
||||||
* challenge-response exchanges.
|
* 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
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface AuthScheme {
|
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.
|
* Returns textual designation of the given authentication scheme.
|
||||||
*
|
*
|
||||||
* @return the name 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 {@code true} if the scheme is connection based, {@code false}
|
||||||
*
|
* if the scheme is request based.
|
||||||
* @return the parameter with the given name
|
|
||||||
*/
|
*/
|
||||||
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
|
* Returns authentication realm. If the concept of an authentication
|
||||||
@ -100,23 +137,58 @@ Header authenticate(
|
|||||||
String getRealm();
|
String getRealm();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests if the authentication scheme is provides authorization on a per
|
* Determines whether or not an authorization response can be generated based on
|
||||||
* connection basis instead of usual per request basis
|
* 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}
|
* @param credentialsProvider The credentials to be used for authentication
|
||||||
* if the scheme is request based.
|
* @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.
|
* Returns {@link Principal} whose credentials are used to generate
|
||||||
* This method tests if the authorization process has been completed, either
|
* an authentication response. Connection based schemes are required
|
||||||
* successfully or unsuccessfully, that is, all the required authorization
|
* to return a user {@link Principal} if authorization applies to
|
||||||
* challenges have been processed in their entirety.
|
* for the entire life span of connection.
|
||||||
|
* @return user principle
|
||||||
*
|
*
|
||||||
* @return {@code true} if the authentication process has been completed,
|
* @see #isConnectionBased()
|
||||||
* {@code false} otherwise.
|
*
|
||||||
|
* @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 */
|
/** Actual authentication scheme */
|
||||||
private AuthScheme authScheme;
|
private AuthScheme authScheme;
|
||||||
|
|
||||||
/** Credentials selected for authentication */
|
|
||||||
private Credentials credentials;
|
|
||||||
|
|
||||||
/** Available auth options */
|
/** Available auth options */
|
||||||
private Queue<AuthOption> authOptions;
|
private Queue<AuthScheme> authOptions;
|
||||||
|
|
||||||
public AuthState() {
|
public AuthState() {
|
||||||
super();
|
super();
|
||||||
@ -65,7 +62,6 @@ public void reset() {
|
|||||||
this.state = AuthProtocolState.UNCHALLENGED;
|
this.state = AuthProtocolState.UNCHALLENGED;
|
||||||
this.authOptions = null;
|
this.authOptions = null;
|
||||||
this.authScheme = null;
|
this.authScheme = null;
|
||||||
this.credentials = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,71 +86,48 @@ public AuthScheme getAuthScheme() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns actual {@link Credentials}. May be null.
|
* Updates the auth state with {@link AuthScheme} and clears auth options.
|
||||||
*/
|
|
||||||
public Credentials getCredentials() {
|
|
||||||
return this.credentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the auth state with {@link AuthScheme} and {@link Credentials}.
|
|
||||||
*
|
*
|
||||||
* @param authScheme auth scheme. May not be null.
|
* @param authScheme auth scheme. May not be null.
|
||||||
* @param credentials user crednetials. May not be null.
|
|
||||||
*
|
*
|
||||||
* @since 4.2
|
* @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(authScheme, "Auth scheme");
|
||||||
Args.notNull(credentials, "Credentials");
|
|
||||||
this.authScheme = authScheme;
|
this.authScheme = authScheme;
|
||||||
this.credentials = credentials;
|
|
||||||
this.authOptions = null;
|
this.authOptions = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns available {@link AuthOption}s. May be null.
|
* Returns available auth options. May be null.
|
||||||
*
|
*
|
||||||
* @since 4.2
|
* @since 4.2
|
||||||
*/
|
*/
|
||||||
public Queue<AuthOption> getAuthOptions() {
|
public Queue<AuthScheme> getAuthOptions() {
|
||||||
return this.authOptions;
|
return this.authOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if {@link AuthOption}s are available, {@code false}
|
* Updates the auth state with a queue of auth options.
|
||||||
* 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.
|
|
||||||
*
|
*
|
||||||
* @param authOptions a queue of auth options. May not be null or empty.
|
* @param authOptions a queue of auth options. May not be null or empty.
|
||||||
*
|
*
|
||||||
* @since 4.2
|
* @since 4.2
|
||||||
*/
|
*/
|
||||||
public void update(final Queue<AuthOption> authOptions) {
|
public void update(final Queue<AuthScheme> authOptions) {
|
||||||
Args.notEmpty(authOptions, "Queue of auth options");
|
Args.notEmpty(authOptions, "Queue of auth options");
|
||||||
this.authOptions = authOptions;
|
this.authOptions = authOptions;
|
||||||
this.authScheme = null;
|
this.authScheme = null;
|
||||||
this.credentials = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
final StringBuilder buffer = new StringBuilder();
|
final StringBuilder buffer = new StringBuilder();
|
||||||
buffer.append("state:").append(this.state).append(";");
|
buffer.append("[").append(this.state);
|
||||||
if (this.authScheme != null) {
|
if (this.authScheme != null) {
|
||||||
buffer.append("auth scheme:").append(this.authScheme.getSchemeName()).append(";");
|
buffer.append(" ").append(this.authScheme);
|
||||||
}
|
|
||||||
if (this.credentials != null) {
|
|
||||||
buffer.append("credentials present");
|
|
||||||
}
|
}
|
||||||
|
buffer.append("]");
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,9 +38,7 @@
|
|||||||
import org.apache.http.annotation.Immutable;
|
import org.apache.http.annotation.Immutable;
|
||||||
import org.apache.http.auth.AuthProtocolState;
|
import org.apache.http.auth.AuthProtocolState;
|
||||||
import org.apache.http.auth.AuthScheme;
|
import org.apache.http.auth.AuthScheme;
|
||||||
import org.apache.http.auth.AuthScope;
|
|
||||||
import org.apache.http.auth.AuthState;
|
import org.apache.http.auth.AuthState;
|
||||||
import org.apache.http.auth.Credentials;
|
|
||||||
import org.apache.http.auth.CredentialsProvider;
|
import org.apache.http.auth.CredentialsProvider;
|
||||||
import org.apache.http.client.AuthCache;
|
import org.apache.http.client.AuthCache;
|
||||||
import org.apache.http.conn.routing.RouteInfo;
|
import org.apache.http.conn.routing.RouteInfo;
|
||||||
@ -106,7 +104,10 @@ public void process(final HttpRequest request, final HttpContext context)
|
|||||||
if (targetState != null && targetState.getState() == AuthProtocolState.UNCHALLENGED) {
|
if (targetState != null && targetState.getState() == AuthProtocolState.UNCHALLENGED) {
|
||||||
final AuthScheme authScheme = authCache.get(target);
|
final AuthScheme authScheme = authCache.get(target);
|
||||||
if (authScheme != null) {
|
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 void process(final HttpRequest request, final HttpContext context)
|
|||||||
if (proxy != null && proxyState != null && proxyState.getState() == AuthProtocolState.UNCHALLENGED) {
|
if (proxy != null && proxyState != null && proxyState.getState() == AuthProtocolState.UNCHALLENGED) {
|
||||||
final AuthScheme authScheme = authCache.get(proxy);
|
final AuthScheme authScheme = authCache.get(proxy);
|
||||||
if (authScheme != null) {
|
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 @@
|
|||||||
public interface CookieAttributeHandler {
|
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.
|
* {@link org.apache.http.cookie.Cookie} property.
|
||||||
*
|
*
|
||||||
* @param cookie {@link org.apache.http.cookie.Cookie} to be updated
|
* @param cookie {@link org.apache.http.cookie.Cookie} to be updated
|
||||||
|
@ -54,7 +54,7 @@ private int getPathLength(final Cookie cookie) {
|
|||||||
public int compare(final Cookie c1, final Cookie c2) {
|
public int compare(final Cookie c1, final Cookie c2) {
|
||||||
final int l1 = getPathLength(c1);
|
final int l1 = getPathLength(c1);
|
||||||
final int l2 = getPathLength(c2);
|
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;
|
final int result = l2 - l1;
|
||||||
if (result == 0 && c1 instanceof BasicClientCookie && c2 instanceof BasicClientCookie) {
|
if (result == 0 && c1 instanceof BasicClientCookie && c2 instanceof BasicClientCookie) {
|
||||||
final Date d1 = ((BasicClientCookie) c1).getCreationDate();
|
final Date d1 = ((BasicClientCookie) c1).getCreationDate();
|
||||||
|
@ -30,23 +30,29 @@
|
|||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.io.ObjectStreamException;
|
import java.io.ObjectStreamException;
|
||||||
|
import java.io.Serializable;
|
||||||
import java.nio.charset.Charset;
|
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.commons.codec.binary.Base64;
|
||||||
import org.apache.http.Consts;
|
import org.apache.http.Consts;
|
||||||
import org.apache.http.Header;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.HttpHeaders;
|
|
||||||
import org.apache.http.HttpRequest;
|
import org.apache.http.HttpRequest;
|
||||||
|
import org.apache.http.NameValuePair;
|
||||||
import org.apache.http.annotation.NotThreadSafe;
|
import org.apache.http.annotation.NotThreadSafe;
|
||||||
import org.apache.http.auth.AuthChallenge;
|
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.AuthenticationException;
|
||||||
import org.apache.http.auth.ChallengeType;
|
|
||||||
import org.apache.http.auth.Credentials;
|
import org.apache.http.auth.Credentials;
|
||||||
|
import org.apache.http.auth.CredentialsProvider;
|
||||||
import org.apache.http.auth.MalformedChallengeException;
|
import org.apache.http.auth.MalformedChallengeException;
|
||||||
import org.apache.http.message.BufferedHeader;
|
|
||||||
import org.apache.http.protocol.HttpContext;
|
import org.apache.http.protocol.HttpContext;
|
||||||
import org.apache.http.util.Args;
|
import org.apache.http.util.Args;
|
||||||
import org.apache.http.util.CharArrayBuffer;
|
|
||||||
import org.apache.http.util.CharsetUtils;
|
import org.apache.http.util.CharsetUtils;
|
||||||
import org.apache.http.util.EncodingUtils;
|
import org.apache.http.util.EncodingUtils;
|
||||||
|
|
||||||
@ -56,17 +62,21 @@
|
|||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
public class BasicScheme extends StandardAuthScheme {
|
public class BasicScheme implements AuthScheme, Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = -1931571557597830536L;
|
private static final long serialVersionUID = -1931571557597830536L;
|
||||||
|
|
||||||
|
private final Map<String, String> paramMap;
|
||||||
private transient Charset charset;
|
private transient Charset charset;
|
||||||
private boolean complete;
|
private boolean complete;
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 4.3
|
* @since 4.3
|
||||||
*/
|
*/
|
||||||
public BasicScheme(final Charset charset) {
|
public BasicScheme(final Charset charset) {
|
||||||
|
this.paramMap = new HashMap<>();
|
||||||
this.charset = charset != null ? charset : Consts.ASCII;
|
this.charset = charset != null ? charset : Consts.ASCII;
|
||||||
this.complete = false;
|
this.complete = false;
|
||||||
}
|
}
|
||||||
@ -75,54 +85,88 @@ public BasicScheme() {
|
|||||||
this(Consts.ASCII);
|
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
|
@Override
|
||||||
public String getSchemeName() {
|
public String getName() {
|
||||||
return "basic";
|
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
|
@Override
|
||||||
public boolean isConnectionBased() {
|
public boolean isConnectionBased() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Header authenticate(
|
public String getRealm() {
|
||||||
final Credentials credentials,
|
return this.paramMap.get("realm");
|
||||||
final HttpRequest request,
|
}
|
||||||
|
|
||||||
|
@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 {
|
final HttpContext context) throws AuthenticationException {
|
||||||
|
|
||||||
Args.notNull(credentials, "Credentials");
|
Args.notNull(host, "Auth host");
|
||||||
Args.notNull(request, "HTTP request");
|
Args.notNull(credentialsProvider, "CredentialsProvider");
|
||||||
final CharArrayBuffer buffer = new CharArrayBuffer(32);
|
|
||||||
if (isProxy()) {
|
final Credentials credentials = credentialsProvider.getCredentials(new AuthScope(host, getRealm(), getName()));
|
||||||
buffer.append(HttpHeaders.PROXY_AUTHORIZATION);
|
if (credentials != null) {
|
||||||
|
this.username = credentials.getUserPrincipal().getName();
|
||||||
|
this.password = credentials.getPassword();
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
buffer.append(HttpHeaders.AUTHORIZATION);
|
this.username = null;
|
||||||
|
this.password = null;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
buffer.append(": Basic ");
|
}
|
||||||
|
|
||||||
final StringBuilder tmp = new StringBuilder();
|
@Override
|
||||||
tmp.append(credentials.getUserPrincipal().getName());
|
public Principal getPrinciple() {
|
||||||
tmp.append(":");
|
return null;
|
||||||
tmp.append((credentials.getPassword() == null) ? "null" : credentials.getPassword());
|
}
|
||||||
|
|
||||||
|
@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 Base64 base64codec = new Base64(0);
|
||||||
final byte[] base64password = base64codec.encode(EncodingUtils.getBytes(tmp.toString(), charset.name()));
|
final byte[] encodedCreds = base64codec.encode(EncodingUtils.getBytes(buffer.toString(), charset.name()));
|
||||||
|
return "Basic " + new String(encodedCreds, 0, encodedCreds.length, Consts.ASCII);
|
||||||
buffer.append(base64password, 0, base64password.length);
|
|
||||||
return new BufferedHeader(buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeObject(final ObjectOutputStream out) throws IOException {
|
private void writeObject(final ObjectOutputStream out) throws IOException {
|
||||||
@ -142,4 +186,9 @@ private void readObject(final ObjectInputStream in) throws IOException, ClassNot
|
|||||||
private void readObjectNoData() throws ObjectStreamException {
|
private void readObjectNoData() throws ObjectStreamException {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.paramMap.toString();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,30 +27,35 @@
|
|||||||
package org.apache.http.impl.auth;
|
package org.apache.http.impl.auth;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.Serializable;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
|
import java.security.Principal;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Formatter;
|
import java.util.Formatter;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.HttpEntity;
|
||||||
import org.apache.http.HttpEntityEnclosingRequest;
|
import org.apache.http.HttpEntityEnclosingRequest;
|
||||||
import org.apache.http.HttpHeaders;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.HttpRequest;
|
import org.apache.http.HttpRequest;
|
||||||
|
import org.apache.http.NameValuePair;
|
||||||
import org.apache.http.annotation.NotThreadSafe;
|
import org.apache.http.annotation.NotThreadSafe;
|
||||||
import org.apache.http.auth.AuthChallenge;
|
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.AuthenticationException;
|
||||||
import org.apache.http.auth.ChallengeType;
|
|
||||||
import org.apache.http.auth.Credentials;
|
import org.apache.http.auth.Credentials;
|
||||||
|
import org.apache.http.auth.CredentialsProvider;
|
||||||
import org.apache.http.auth.MalformedChallengeException;
|
import org.apache.http.auth.MalformedChallengeException;
|
||||||
import org.apache.http.message.BasicHeaderValueFormatter;
|
import org.apache.http.message.BasicHeaderValueFormatter;
|
||||||
import org.apache.http.message.BasicNameValuePair;
|
import org.apache.http.message.BasicNameValuePair;
|
||||||
import org.apache.http.message.BufferedHeader;
|
|
||||||
import org.apache.http.protocol.HttpContext;
|
import org.apache.http.protocol.HttpContext;
|
||||||
import org.apache.http.util.Args;
|
import org.apache.http.util.Args;
|
||||||
import org.apache.http.util.CharArrayBuffer;
|
import org.apache.http.util.CharArrayBuffer;
|
||||||
@ -71,7 +76,7 @@
|
|||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
public class DigestScheme extends StandardAuthScheme {
|
public class DigestScheme implements AuthScheme, Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 3883908186234566916L;
|
private static final long serialVersionUID = 3883908186234566916L;
|
||||||
|
|
||||||
@ -86,49 +91,37 @@ public class DigestScheme extends StandardAuthScheme {
|
|||||||
'e', 'f'
|
'e', 'f'
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Whether the digest authentication process is complete */
|
|
||||||
private boolean complete;
|
|
||||||
|
|
||||||
private static final int QOP_UNKNOWN = -1;
|
private static final int QOP_UNKNOWN = -1;
|
||||||
private static final int QOP_MISSING = 0;
|
private static final int QOP_MISSING = 0;
|
||||||
private static final int QOP_AUTH_INT = 1;
|
private static final int QOP_AUTH_INT = 1;
|
||||||
private static final int QOP_AUTH = 2;
|
private static final int QOP_AUTH = 2;
|
||||||
|
|
||||||
|
private final Map<String, String> paramMap;
|
||||||
|
private boolean complete;
|
||||||
private String lastNonce;
|
private String lastNonce;
|
||||||
private long nounceCount;
|
private long nounceCount;
|
||||||
private String cnonce;
|
private String cnonce;
|
||||||
private String a1;
|
private String a1;
|
||||||
private String a2;
|
private String a2;
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
|
||||||
public DigestScheme() {
|
public DigestScheme() {
|
||||||
|
this.paramMap = new HashMap<>();
|
||||||
this.complete = false;
|
this.complete = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void initPreemptive(final Credentials credentials, final String cnonce, final String realm) {
|
||||||
public void processChallenge(
|
Args.notNull(credentials, "Credentials");
|
||||||
final ChallengeType challengeType,
|
this.username = credentials.getUserPrincipal().getName();
|
||||||
final AuthChallenge authChallenge) throws MalformedChallengeException {
|
this.password = credentials.getPassword();
|
||||||
Args.notNull(challengeType, "ChallengeType");
|
this.paramMap.put("cnonce", cnonce);
|
||||||
Args.notNull(authChallenge, "AuthChallenge");
|
this.paramMap.put("realm", realm);
|
||||||
update(challengeType, authChallenge);
|
|
||||||
if (getParameters().isEmpty()) {
|
|
||||||
throw new MalformedChallengeException("Missing digest auth parameters");
|
|
||||||
}
|
|
||||||
this.complete = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isComplete() {
|
public String getName() {
|
||||||
final String s = getParameter("stale");
|
|
||||||
if ("true".equalsIgnoreCase(s)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return this.complete;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSchemeName() {
|
|
||||||
return "digest";
|
return "digest";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,28 +130,79 @@ public boolean isConnectionBased() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void overrideParamter(final String name, final String value) {
|
@Override
|
||||||
getParameters().put(name, value);
|
public String getRealm() {
|
||||||
|
return this.paramMap.get("realm");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Header authenticate(
|
public void processChallenge(
|
||||||
final Credentials credentials,
|
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 HttpRequest request,
|
||||||
final HttpContext context) throws AuthenticationException {
|
final HttpContext context) throws AuthenticationException {
|
||||||
|
|
||||||
Args.notNull(credentials, "Credentials");
|
|
||||||
Args.notNull(request, "HTTP request");
|
Args.notNull(request, "HTTP request");
|
||||||
if (getParameter("realm") == null) {
|
if (this.paramMap.get("realm") == null) {
|
||||||
throw new AuthenticationException("missing realm in challenge");
|
throw new AuthenticationException("missing realm");
|
||||||
}
|
}
|
||||||
if (getParameter("nonce") == null) {
|
if (this.paramMap.get("nonce") == null) {
|
||||||
throw new AuthenticationException("missing nonce in challenge");
|
throw new AuthenticationException("missing nonce");
|
||||||
}
|
}
|
||||||
// Add method name and request-URI to the parameter map
|
return createDigestResponse(request);
|
||||||
getParameters().put("methodname", request.getRequestLine().getMethod());
|
|
||||||
getParameters().put("uri", request.getRequestLine().getUri());
|
|
||||||
return createDigestHeader(credentials, request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MessageDigest createMessageDigest(
|
private static MessageDigest createMessageDigest(
|
||||||
@ -172,15 +216,14 @@ private static MessageDigest createMessageDigest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Header createDigestHeader(
|
private String createDigestResponse(final HttpRequest request) throws AuthenticationException {
|
||||||
final Credentials credentials,
|
|
||||||
final HttpRequest request) throws AuthenticationException {
|
final String uri = request.getRequestLine().getUri();
|
||||||
final String uri = getParameter("uri");
|
final String method = request.getRequestLine().getMethod();
|
||||||
final String realm = getParameter("realm");
|
final String realm = this.paramMap.get("realm");
|
||||||
final String nonce = getParameter("nonce");
|
final String nonce = this.paramMap.get("nonce");
|
||||||
final String opaque = getParameter("opaque");
|
final String opaque = this.paramMap.get("opaque");
|
||||||
final String method = getParameter("methodname");
|
String algorithm = this.paramMap.get("algorithm");
|
||||||
String algorithm = getParameter("algorithm");
|
|
||||||
// If an algorithm is not specified, default to MD5.
|
// If an algorithm is not specified, default to MD5.
|
||||||
if (algorithm == null) {
|
if (algorithm == null) {
|
||||||
algorithm = "MD5";
|
algorithm = "MD5";
|
||||||
@ -188,7 +231,7 @@ private Header createDigestHeader(
|
|||||||
|
|
||||||
final Set<String> qopset = new HashSet<>(8);
|
final Set<String> qopset = new HashSet<>(8);
|
||||||
int qop = QOP_UNKNOWN;
|
int qop = QOP_UNKNOWN;
|
||||||
final String qoplist = getParameter("qop");
|
final String qoplist = this.paramMap.get("qop");
|
||||||
if (qoplist != null) {
|
if (qoplist != null) {
|
||||||
final StringTokenizer tok = new StringTokenizer(qoplist, ",");
|
final StringTokenizer tok = new StringTokenizer(qoplist, ",");
|
||||||
while (tok.hasMoreTokens()) {
|
while (tok.hasMoreTokens()) {
|
||||||
@ -208,7 +251,7 @@ private Header createDigestHeader(
|
|||||||
throw new AuthenticationException("None of the qop methods is supported: " + qoplist);
|
throw new AuthenticationException("None of the qop methods is supported: " + qoplist);
|
||||||
}
|
}
|
||||||
|
|
||||||
String charset = getParameter("charset");
|
String charset = this.paramMap.get("charset");
|
||||||
if (charset == null) {
|
if (charset == null) {
|
||||||
charset = "ISO-8859-1";
|
charset = "ISO-8859-1";
|
||||||
}
|
}
|
||||||
@ -225,9 +268,6 @@ private Header createDigestHeader(
|
|||||||
throw new AuthenticationException("Unsuppported digest algorithm: " + digAlg);
|
throw new AuthenticationException("Unsuppported digest algorithm: " + digAlg);
|
||||||
}
|
}
|
||||||
|
|
||||||
final String uname = credentials.getUserPrincipal().getName();
|
|
||||||
final String pwd = credentials.getPassword();
|
|
||||||
|
|
||||||
if (nonce.equals(this.lastNonce)) {
|
if (nonce.equals(this.lastNonce)) {
|
||||||
nounceCount++;
|
nounceCount++;
|
||||||
} else {
|
} else {
|
||||||
@ -255,7 +295,7 @@ private Header createDigestHeader(
|
|||||||
|
|
||||||
// calculated one per session
|
// calculated one per session
|
||||||
sb.setLength(0);
|
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)));
|
final String checksum = encode(digester.digest(EncodingUtils.getBytes(sb.toString(), charset)));
|
||||||
sb.setLength(0);
|
sb.setLength(0);
|
||||||
sb.append(checksum).append(':').append(nonce).append(':').append(cnonce);
|
sb.append(checksum).append(':').append(nonce).append(':').append(cnonce);
|
||||||
@ -263,7 +303,7 @@ private Header createDigestHeader(
|
|||||||
} else {
|
} else {
|
||||||
// unq(username-value) ":" unq(realm-value) ":" passwd
|
// unq(username-value) ":" unq(realm-value) ":" passwd
|
||||||
sb.setLength(0);
|
sb.setLength(0);
|
||||||
sb.append(uname).append(':').append(realm).append(':').append(pwd);
|
sb.append(username).append(':').append(realm).append(':').append(password);
|
||||||
a1 = sb.toString();
|
a1 = sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,15 +363,10 @@ private Header createDigestHeader(
|
|||||||
final String digest = encode(digester.digest(EncodingUtils.getAsciiBytes(digestValue)));
|
final String digest = encode(digester.digest(EncodingUtils.getAsciiBytes(digestValue)));
|
||||||
|
|
||||||
final CharArrayBuffer buffer = new CharArrayBuffer(128);
|
final CharArrayBuffer buffer = new CharArrayBuffer(128);
|
||||||
if (isProxy()) {
|
buffer.append("Digest ");
|
||||||
buffer.append(HttpHeaders.PROXY_AUTHORIZATION);
|
|
||||||
} else {
|
|
||||||
buffer.append(HttpHeaders.AUTHORIZATION);
|
|
||||||
}
|
|
||||||
buffer.append(": Digest ");
|
|
||||||
|
|
||||||
final List<BasicNameValuePair> params = new ArrayList<>(20);
|
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("realm", realm));
|
||||||
params.add(new BasicNameValuePair("nonce", nonce));
|
params.add(new BasicNameValuePair("nonce", nonce));
|
||||||
params.add(new BasicNameValuePair("uri", uri));
|
params.add(new BasicNameValuePair("uri", uri));
|
||||||
@ -358,7 +393,7 @@ private Header createDigestHeader(
|
|||||||
|| "algorithm".equals(name));
|
|| "algorithm".equals(name));
|
||||||
BasicHeaderValueFormatter.INSTANCE.formatNameValuePair(buffer, param, !noQuotes);
|
BasicHeaderValueFormatter.INSTANCE.formatNameValuePair(buffer, param, !noQuotes);
|
||||||
}
|
}
|
||||||
return new BufferedHeader(buffer);
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
String getCnonce() {
|
String getCnonce() {
|
||||||
@ -405,4 +440,9 @@ public static String createCnonce() {
|
|||||||
return encode(tmp);
|
return encode(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.paramMap.toString();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,28 +28,25 @@
|
|||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.security.Principal;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
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.HttpHost;
|
||||||
import org.apache.http.HttpRequest;
|
import org.apache.http.HttpRequest;
|
||||||
import org.apache.http.annotation.NotThreadSafe;
|
import org.apache.http.annotation.NotThreadSafe;
|
||||||
import org.apache.http.auth.AuthChallenge;
|
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.AuthenticationException;
|
||||||
import org.apache.http.auth.ChallengeType;
|
|
||||||
import org.apache.http.auth.Credentials;
|
import org.apache.http.auth.Credentials;
|
||||||
|
import org.apache.http.auth.CredentialsProvider;
|
||||||
import org.apache.http.auth.InvalidCredentialsException;
|
import org.apache.http.auth.InvalidCredentialsException;
|
||||||
import org.apache.http.auth.KerberosCredentials;
|
import org.apache.http.auth.KerberosCredentials;
|
||||||
import org.apache.http.auth.MalformedChallengeException;
|
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.protocol.HttpContext;
|
||||||
import org.apache.http.util.Args;
|
import org.apache.http.util.Args;
|
||||||
import org.apache.http.util.CharArrayBuffer;
|
|
||||||
import org.ietf.jgss.GSSContext;
|
import org.ietf.jgss.GSSContext;
|
||||||
import org.ietf.jgss.GSSCredential;
|
import org.ietf.jgss.GSSCredential;
|
||||||
import org.ietf.jgss.GSSException;
|
import org.ietf.jgss.GSSException;
|
||||||
@ -61,7 +58,7 @@
|
|||||||
* @since 4.2
|
* @since 4.2
|
||||||
*/
|
*/
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
public abstract class GGSSchemeBase extends NonStandardAuthScheme {
|
public abstract class GGSSchemeBase implements AuthScheme {
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
UNINITIATED,
|
UNINITIATED,
|
||||||
@ -77,8 +74,8 @@ enum State {
|
|||||||
|
|
||||||
/** Authentication process state */
|
/** Authentication process state */
|
||||||
private State state;
|
private State state;
|
||||||
|
private GSSCredential gssCredential;
|
||||||
/** base64 decoded challenge **/
|
private String challenge;
|
||||||
private byte[] token;
|
private byte[] token;
|
||||||
|
|
||||||
GGSSchemeBase(final boolean stripPort, final boolean useCanonicalHostname) {
|
GGSSchemeBase(final boolean stripPort, final boolean useCanonicalHostname) {
|
||||||
@ -93,19 +90,25 @@ enum State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GGSSchemeBase() {
|
GGSSchemeBase() {
|
||||||
this(true,true);
|
this(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRealm() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void processChallenge(
|
public void processChallenge(
|
||||||
final ChallengeType challengeType,
|
final AuthChallenge authChallenge,
|
||||||
final AuthChallenge authChallenge) throws MalformedChallengeException {
|
final HttpContext context) throws MalformedChallengeException {
|
||||||
update(challengeType, authChallenge);
|
Args.notNull(authChallenge, "AuthChallenge");
|
||||||
|
if (authChallenge.getValue() == null) {
|
||||||
|
throw new MalformedChallengeException("Missing auth challenge");
|
||||||
|
}
|
||||||
|
this.challenge = authChallenge.getValue();
|
||||||
if (state == State.UNINITIATED) {
|
if (state == State.UNINITIATED) {
|
||||||
final String challenge = getChallenge();
|
|
||||||
token = Base64.decodeBase64(challenge.getBytes());
|
token = Base64.decodeBase64(challenge.getBytes());
|
||||||
if (log.isDebugEnabled()) {
|
|
||||||
log.debug("Received token '" + token + "' from the auth server");
|
|
||||||
}
|
|
||||||
state = State.CHALLENGE_RECEIVED;
|
state = State.CHALLENGE_RECEIVED;
|
||||||
} else {
|
} else {
|
||||||
log.debug("Authentication already attempted");
|
log.debug("Authentication already attempted");
|
||||||
@ -117,17 +120,10 @@ protected GSSManager getManager() {
|
|||||||
return GSSManager.getInstance();
|
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
|
* @since 4.4
|
||||||
*/
|
*/
|
||||||
protected byte[] generateGSSToken(
|
protected byte[] generateGSSToken(final byte[] input, final Oid oid, final String authServer) throws GSSException {
|
||||||
final byte[] input, final Oid oid, final String authServer,
|
|
||||||
final Credentials credentials) throws GSSException {
|
|
||||||
byte[] inputBuff = input;
|
byte[] inputBuff = input;
|
||||||
if (inputBuff == null) {
|
if (inputBuff == null) {
|
||||||
inputBuff = new byte[0];
|
inputBuff = new byte[0];
|
||||||
@ -135,13 +131,6 @@ protected byte[] generateGSSToken(
|
|||||||
final GSSManager manager = getManager();
|
final GSSManager manager = getManager();
|
||||||
final GSSName serverName = manager.createName("HTTP@" + authServer, GSSName.NT_HOSTBASED_SERVICE);
|
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(
|
final GSSContext gssContext = manager.createContext(
|
||||||
serverName.canonicalize(oid), oid, gssCredential, GSSContext.DEFAULT_LIFETIME);
|
serverName.canonicalize(oid), oid, gssCredential, GSSContext.DEFAULT_LIFETIME);
|
||||||
gssContext.requestMutualAuth(true);
|
gssContext.requestMutualAuth(true);
|
||||||
@ -152,43 +141,52 @@ protected byte[] generateGSSToken(
|
|||||||
/**
|
/**
|
||||||
* @since 4.4
|
* @since 4.4
|
||||||
*/
|
*/
|
||||||
protected abstract byte[] generateToken(
|
protected abstract byte[] generateToken(byte[] input, String authServer) throws GSSException;
|
||||||
byte[] input, String authServer, Credentials credentials) throws GSSException;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isComplete() {
|
public boolean isChallengeComplete() {
|
||||||
return this.state == State.TOKEN_GENERATED || this.state == State.FAILED;
|
return this.state == State.TOKEN_GENERATED || this.state == State.FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Header authenticate(
|
public boolean isResponseReady(
|
||||||
final Credentials credentials,
|
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 HttpRequest request,
|
||||||
final HttpContext context) throws AuthenticationException {
|
final HttpContext context) throws AuthenticationException {
|
||||||
|
Args.notNull(host, "HTTP host");
|
||||||
Args.notNull(request, "HTTP request");
|
Args.notNull(request, "HTTP request");
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case UNINITIATED:
|
case UNINITIATED:
|
||||||
throw new AuthenticationException(getSchemeName() + " authentication has not been initiated");
|
throw new AuthenticationException(getName() + " authentication has not been initiated");
|
||||||
case FAILED:
|
case FAILED:
|
||||||
throw new AuthenticationException(getSchemeName() + " authentication has failed");
|
throw new AuthenticationException(getName() + " authentication has failed");
|
||||||
case CHALLENGE_RECEIVED:
|
case CHALLENGE_RECEIVED:
|
||||||
try {
|
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;
|
final String authServer;
|
||||||
String hostname = host.getHostName();
|
String hostname = host.getHostName();
|
||||||
|
|
||||||
if (this.useCanonicalHostname){
|
if (this.useCanonicalHostname){
|
||||||
try {
|
try {
|
||||||
//TODO: uncomment this statement and delete the resolveCanonicalHostname,
|
//TODO: uncomment this statement and delete the resolveCanonicalHostname,
|
||||||
@ -208,7 +206,7 @@ public Header authenticate(
|
|||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("init " + authServer);
|
log.debug("init " + authServer);
|
||||||
}
|
}
|
||||||
token = generateToken(token, authServer, credentials);
|
token = generateToken(token, authServer);
|
||||||
state = State.TOKEN_GENERATED;
|
state = State.TOKEN_GENERATED;
|
||||||
} catch (final GSSException gsse) {
|
} catch (final GSSException gsse) {
|
||||||
state = State.FAILED;
|
state = State.FAILED;
|
||||||
@ -233,15 +231,7 @@ public Header authenticate(
|
|||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Sending response '" + tokenstr + "' back to the auth server");
|
log.debug("Sending response '" + tokenstr + "' back to the auth server");
|
||||||
}
|
}
|
||||||
final CharArrayBuffer buffer = new CharArrayBuffer(32);
|
return "Negotiate " + tokenstr;
|
||||||
if (isProxy()) {
|
|
||||||
buffer.append(HttpHeaders.PROXY_AUTHORIZATION);
|
|
||||||
} else {
|
|
||||||
buffer.append(HttpHeaders.AUTHORIZATION);
|
|
||||||
}
|
|
||||||
buffer.append(": Negotiate ");
|
|
||||||
buffer.append(tokenstr);
|
|
||||||
return new BufferedHeader(buffer);
|
|
||||||
default:
|
default:
|
||||||
throw new IllegalStateException("Illegal state: " + state);
|
throw new IllegalStateException("Illegal state: " + state);
|
||||||
}
|
}
|
||||||
@ -256,4 +246,9 @@ private String resolveCanonicalHostname(final String host) throws UnknownHostExc
|
|||||||
return canonicalServer;
|
return canonicalServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "[" + this.state + " " + challenge + ']';
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -47,20 +47,18 @@
|
|||||||
import org.apache.http.HttpStatus;
|
import org.apache.http.HttpStatus;
|
||||||
import org.apache.http.ParseException;
|
import org.apache.http.ParseException;
|
||||||
import org.apache.http.auth.AuthChallenge;
|
import org.apache.http.auth.AuthChallenge;
|
||||||
import org.apache.http.auth.AuthOption;
|
|
||||||
import org.apache.http.auth.AuthProtocolState;
|
import org.apache.http.auth.AuthProtocolState;
|
||||||
import org.apache.http.auth.AuthScheme;
|
import org.apache.http.auth.AuthScheme;
|
||||||
import org.apache.http.auth.AuthScope;
|
|
||||||
import org.apache.http.auth.AuthState;
|
import org.apache.http.auth.AuthState;
|
||||||
import org.apache.http.auth.AuthenticationException;
|
import org.apache.http.auth.AuthenticationException;
|
||||||
import org.apache.http.auth.ChallengeType;
|
import org.apache.http.auth.ChallengeType;
|
||||||
import org.apache.http.auth.Credentials;
|
|
||||||
import org.apache.http.auth.CredentialsProvider;
|
import org.apache.http.auth.CredentialsProvider;
|
||||||
import org.apache.http.auth.MalformedChallengeException;
|
import org.apache.http.auth.MalformedChallengeException;
|
||||||
import org.apache.http.client.AuthCache;
|
import org.apache.http.client.AuthCache;
|
||||||
import org.apache.http.client.AuthenticationStrategy;
|
import org.apache.http.client.AuthenticationStrategy;
|
||||||
import org.apache.http.client.config.AuthSchemes;
|
import org.apache.http.client.config.AuthSchemes;
|
||||||
import org.apache.http.client.protocol.HttpClientContext;
|
import org.apache.http.client.protocol.HttpClientContext;
|
||||||
|
import org.apache.http.message.BasicHeader;
|
||||||
import org.apache.http.message.ParserCursor;
|
import org.apache.http.message.ParserCursor;
|
||||||
import org.apache.http.protocol.HttpContext;
|
import org.apache.http.protocol.HttpContext;
|
||||||
import org.apache.http.util.Asserts;
|
import org.apache.http.util.Asserts;
|
||||||
@ -195,12 +193,12 @@ public boolean prepareAuthResponse(
|
|||||||
case UNCHALLENGED:
|
case UNCHALLENGED:
|
||||||
final AuthScheme authScheme = authState.getAuthScheme();
|
final AuthScheme authScheme = authState.getAuthScheme();
|
||||||
if (authScheme != null) {
|
if (authScheme != null) {
|
||||||
final String id = authScheme.getSchemeName();
|
final String id = authScheme.getName();
|
||||||
final AuthChallenge challenge = challengeMap.get(id.toLowerCase(Locale.ROOT));
|
final AuthChallenge challenge = challengeMap.get(id.toLowerCase(Locale.ROOT));
|
||||||
if (challenge != null) {
|
if (challenge != null) {
|
||||||
this.log.debug("Authorization challenge processed");
|
this.log.debug("Authorization challenge processed");
|
||||||
try {
|
try {
|
||||||
authScheme.processChallenge(challengeType, challenge);
|
authScheme.processChallenge(challenge, context);
|
||||||
} catch (MalformedChallengeException ex) {
|
} catch (MalformedChallengeException ex) {
|
||||||
if (this.log.isWarnEnabled()) {
|
if (this.log.isWarnEnabled()) {
|
||||||
this.log.warn(ex.getMessage());
|
this.log.warn(ex.getMessage());
|
||||||
@ -209,7 +207,7 @@ public boolean prepareAuthResponse(
|
|||||||
authState.reset();
|
authState.reset();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (authScheme.isComplete()) {
|
if (authScheme.isChallengeComplete()) {
|
||||||
this.log.debug("Authentication failed");
|
this.log.debug("Authentication failed");
|
||||||
clearCache(host, clientContext);
|
clearCache(host, clientContext);
|
||||||
authState.reset();
|
authState.reset();
|
||||||
@ -233,22 +231,16 @@ public boolean prepareAuthResponse(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Queue<AuthOption> authOptions = new LinkedList<>();
|
final Queue<AuthScheme> authOptions = new LinkedList<>();
|
||||||
for (AuthScheme authScheme: preferredSchemes) {
|
for (AuthScheme authScheme: preferredSchemes) {
|
||||||
try {
|
try {
|
||||||
final String id = authScheme.getSchemeName();
|
final String id = authScheme.getName();
|
||||||
final AuthChallenge challenge = challengeMap.get(id.toLowerCase(Locale.ROOT));
|
final AuthChallenge challenge = challengeMap.get(id.toLowerCase(Locale.ROOT));
|
||||||
authScheme.processChallenge(challengeType, challenge);
|
authScheme.processChallenge(challenge, context);
|
||||||
final AuthScope authScope = new AuthScope(
|
if (authScheme.isResponseReady(host, credsProvider, context)) {
|
||||||
host.getHostName(),
|
authOptions.add(authScheme);
|
||||||
host.getPort(),
|
|
||||||
authScheme.getRealm(),
|
|
||||||
authScheme.getSchemeName());
|
|
||||||
final Credentials credentials = credsProvider.getCredentials(authScope);
|
|
||||||
if (credentials != null) {
|
|
||||||
authOptions.add(new AuthOption(authScheme, credentials));
|
|
||||||
}
|
}
|
||||||
} catch (MalformedChallengeException ex) {
|
} catch (AuthenticationException | MalformedChallengeException ex) {
|
||||||
if (this.log.isWarnEnabled()) {
|
if (this.log.isWarnEnabled()) {
|
||||||
this.log.warn(ex.getMessage());
|
this.log.warn(ex.getMessage());
|
||||||
}
|
}
|
||||||
@ -267,11 +259,12 @@ public boolean prepareAuthResponse(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addAuthResponse(
|
public void addAuthResponse(
|
||||||
|
final HttpHost host,
|
||||||
|
final ChallengeType challengeType,
|
||||||
final HttpRequest request,
|
final HttpRequest request,
|
||||||
final AuthState authState,
|
final AuthState authState,
|
||||||
final HttpContext context) throws HttpException, IOException {
|
final HttpContext context) throws HttpException, IOException {
|
||||||
AuthScheme authScheme = authState.getAuthScheme();
|
AuthScheme authScheme = authState.getAuthScheme();
|
||||||
Credentials creds = authState.getCredentials();
|
|
||||||
switch (authState.getState()) {
|
switch (authState.getState()) {
|
||||||
case FAILURE:
|
case FAILURE:
|
||||||
return;
|
return;
|
||||||
@ -285,19 +278,20 @@ public void addAuthResponse(
|
|||||||
Asserts.notNull(authScheme, "AuthScheme");
|
Asserts.notNull(authScheme, "AuthScheme");
|
||||||
break;
|
break;
|
||||||
case CHALLENGED:
|
case CHALLENGED:
|
||||||
final Queue<AuthOption> authOptions = authState.getAuthOptions();
|
final Queue<AuthScheme> authOptions = authState.getAuthOptions();
|
||||||
if (authOptions != null) {
|
if (authOptions != null) {
|
||||||
while (!authOptions.isEmpty()) {
|
while (!authOptions.isEmpty()) {
|
||||||
final AuthOption authOption = authOptions.remove();
|
authScheme = authOptions.remove();
|
||||||
authScheme = authOption.getAuthScheme();
|
authState.update(authScheme);
|
||||||
creds = authOption.getCredentials();
|
|
||||||
authState.update(authScheme, creds);
|
|
||||||
if (this.log.isDebugEnabled()) {
|
if (this.log.isDebugEnabled()) {
|
||||||
this.log.debug("Generating response to an authentication challenge using "
|
this.log.debug("Generating response to an authentication challenge using "
|
||||||
+ authScheme.getSchemeName() + " scheme");
|
+ authScheme.getName() + " scheme");
|
||||||
}
|
}
|
||||||
try {
|
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);
|
request.addHeader(header);
|
||||||
break;
|
break;
|
||||||
} catch (final AuthenticationException ex) {
|
} catch (final AuthenticationException ex) {
|
||||||
@ -314,7 +308,10 @@ public void addAuthResponse(
|
|||||||
}
|
}
|
||||||
if (authScheme != null) {
|
if (authScheme != null) {
|
||||||
try {
|
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);
|
request.addHeader(header);
|
||||||
} catch (final AuthenticationException ex) {
|
} catch (final AuthenticationException ex) {
|
||||||
if (this.log.isErrorEnabled()) {
|
if (this.log.isErrorEnabled()) {
|
||||||
@ -325,7 +322,7 @@ public void addAuthResponse(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isCachable(final AuthScheme authScheme) {
|
private boolean isCachable(final AuthScheme authScheme) {
|
||||||
final String schemeName = authScheme.getSchemeName();
|
final String schemeName = authScheme.getName();
|
||||||
return schemeName.equalsIgnoreCase(AuthSchemes.BASIC) ||
|
return schemeName.equalsIgnoreCase(AuthSchemes.BASIC) ||
|
||||||
schemeName.equalsIgnoreCase(AuthSchemes.DIGEST);
|
schemeName.equalsIgnoreCase(AuthSchemes.DIGEST);
|
||||||
}
|
}
|
||||||
@ -335,7 +332,7 @@ private void updateCache(final HttpHost host, final AuthScheme authScheme, final
|
|||||||
final AuthCache authCache = clientContext.getAuthCache();
|
final AuthCache authCache = clientContext.getAuthCache();
|
||||||
if (authCache != null) {
|
if (authCache != null) {
|
||||||
if (this.log.isDebugEnabled()) {
|
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);
|
authCache.put(host, authScheme);
|
||||||
}
|
}
|
||||||
@ -353,12 +350,4 @@ private void clearCache(final HttpHost host, final HttpClientContext clientConte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
package org.apache.http.impl.auth;
|
||||||
|
|
||||||
import org.apache.http.annotation.NotThreadSafe;
|
import org.apache.http.annotation.NotThreadSafe;
|
||||||
import org.apache.http.auth.Credentials;
|
|
||||||
import org.ietf.jgss.GSSException;
|
import org.ietf.jgss.GSSException;
|
||||||
import org.ietf.jgss.Oid;
|
import org.ietf.jgss.Oid;
|
||||||
|
|
||||||
@ -57,13 +56,13 @@ public KerberosScheme() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSchemeName() {
|
public String getName() {
|
||||||
return "Kerberos";
|
return "Kerberos";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected byte[] generateToken(final byte[] input, final String authServer, final Credentials credentials) throws GSSException {
|
protected byte[] generateToken(final byte[] input, final String authServer) throws GSSException {
|
||||||
return generateGSSToken(input, new Oid(KERBEROS_OID), authServer, credentials);
|
return generateGSSToken(input, new Oid(KERBEROS_OID), authServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1574,7 +1574,7 @@ static class HMACMD5 {
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Very important: update the digest with the ipad buffer
|
// Very important: processChallenge the digest with the ipad buffer
|
||||||
md5.reset();
|
md5.reset();
|
||||||
md5.update(ipad);
|
md5.update(ipad);
|
||||||
|
|
||||||
|
@ -26,21 +26,21 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.http.impl.auth;
|
package org.apache.http.impl.auth;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
import java.security.Principal;
|
||||||
import org.apache.http.HttpHeaders;
|
|
||||||
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.HttpRequest;
|
import org.apache.http.HttpRequest;
|
||||||
import org.apache.http.annotation.NotThreadSafe;
|
import org.apache.http.annotation.NotThreadSafe;
|
||||||
import org.apache.http.auth.AuthChallenge;
|
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.AuthenticationException;
|
||||||
import org.apache.http.auth.ChallengeType;
|
|
||||||
import org.apache.http.auth.Credentials;
|
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.MalformedChallengeException;
|
||||||
import org.apache.http.auth.NTCredentials;
|
import org.apache.http.auth.NTCredentials;
|
||||||
import org.apache.http.message.BufferedHeader;
|
|
||||||
import org.apache.http.protocol.HttpContext;
|
import org.apache.http.protocol.HttpContext;
|
||||||
import org.apache.http.util.Args;
|
import org.apache.http.util.Args;
|
||||||
import org.apache.http.util.CharArrayBuffer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NTLM is a proprietary authentication scheme developed by Microsoft
|
* NTLM is a proprietary authentication scheme developed by Microsoft
|
||||||
@ -49,7 +49,7 @@
|
|||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
public class NTLMScheme extends NonStandardAuthScheme {
|
public class NTLMScheme implements AuthScheme {
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
UNINITIATED,
|
UNINITIATED,
|
||||||
@ -63,6 +63,8 @@ enum State {
|
|||||||
private final NTLMEngine engine;
|
private final NTLMEngine engine;
|
||||||
|
|
||||||
private State state;
|
private State state;
|
||||||
|
private String challenge;
|
||||||
|
private NTCredentials credentials;
|
||||||
|
|
||||||
public NTLMScheme(final NTLMEngine engine) {
|
public NTLMScheme(final NTLMEngine engine) {
|
||||||
super();
|
super();
|
||||||
@ -79,7 +81,7 @@ public NTLMScheme() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSchemeName() {
|
public String getName() {
|
||||||
return "ntlm";
|
return "ntlm";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,13 +90,21 @@ public boolean isConnectionBased() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRealm() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processChallenge(
|
public void processChallenge(
|
||||||
final ChallengeType challengeType, final AuthChallenge authChallenge) throws MalformedChallengeException {
|
final AuthChallenge authChallenge,
|
||||||
Args.notNull(challengeType, "ChallengeType");
|
final HttpContext context) throws MalformedChallengeException {
|
||||||
Args.notNull(authChallenge, "AuthChallenge");
|
Args.notNull(authChallenge, "AuthChallenge");
|
||||||
final String value = authChallenge.getValue();
|
if (authChallenge.getValue() == null) {
|
||||||
if (value == null || value.isEmpty()) {
|
throw new MalformedChallengeException("Missing auth challenge");
|
||||||
|
}
|
||||||
|
this.challenge = authChallenge.getValue();
|
||||||
|
if (this.challenge == null || this.challenge.isEmpty()) {
|
||||||
if (this.state == State.UNINITIATED) {
|
if (this.state == State.UNINITIATED) {
|
||||||
this.state = State.CHALLENGE_RECEIVED;
|
this.state = State.CHALLENGE_RECEIVED;
|
||||||
} else {
|
} else {
|
||||||
@ -111,51 +121,66 @@ public void processChallenge(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Header authenticate(
|
public boolean isResponseReady(
|
||||||
final Credentials credentials,
|
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 HttpRequest request,
|
||||||
final HttpContext context) throws AuthenticationException {
|
final HttpContext context) throws AuthenticationException {
|
||||||
final NTCredentials ntcredentials;
|
if (this.credentials == null) {
|
||||||
try {
|
throw new AuthenticationException("NT credentials not available");
|
||||||
ntcredentials = (NTCredentials) credentials;
|
|
||||||
} catch (final ClassCastException e) {
|
|
||||||
throw new InvalidCredentialsException(
|
|
||||||
"Credentials cannot be used for NTLM authentication: "
|
|
||||||
+ credentials.getClass().getName());
|
|
||||||
}
|
}
|
||||||
final String response;
|
final String response;
|
||||||
if (this.state == State.FAILED) {
|
if (this.state == State.FAILED) {
|
||||||
throw new AuthenticationException("NTLM authentication failed");
|
throw new AuthenticationException("NTLM authentication failed");
|
||||||
} else if (this.state == State.CHALLENGE_RECEIVED) {
|
} else if (this.state == State.CHALLENGE_RECEIVED) {
|
||||||
response = this.engine.generateType1Msg(
|
response = this.engine.generateType1Msg(
|
||||||
ntcredentials.getNetbiosDomain(),
|
this.credentials.getNetbiosDomain(),
|
||||||
ntcredentials.getWorkstation());
|
this.credentials.getWorkstation());
|
||||||
this.state = State.MSG_TYPE1_GENERATED;
|
this.state = State.MSG_TYPE1_GENERATED;
|
||||||
} else if (this.state == State.MSG_TYPE2_RECEVIED) {
|
} else if (this.state == State.MSG_TYPE2_RECEVIED) {
|
||||||
response = this.engine.generateType3Msg(
|
response = this.engine.generateType3Msg(
|
||||||
ntcredentials.getUserName(),
|
this.credentials.getUserName(),
|
||||||
ntcredentials.getPassword(),
|
this.credentials.getPassword(),
|
||||||
ntcredentials.getNetbiosDomain(),
|
this.credentials.getNetbiosDomain(),
|
||||||
ntcredentials.getWorkstation(),
|
this.credentials.getWorkstation(),
|
||||||
getChallenge());
|
this.challenge);
|
||||||
this.state = State.MSG_TYPE3_GENERATED;
|
this.state = State.MSG_TYPE3_GENERATED;
|
||||||
} else {
|
} else {
|
||||||
throw new AuthenticationException("Unexpected state: " + this.state);
|
throw new AuthenticationException("Unexpected state: " + this.state);
|
||||||
}
|
}
|
||||||
final CharArrayBuffer buffer = new CharArrayBuffer(32);
|
return "NTLM " + response;
|
||||||
if (isProxy()) {
|
|
||||||
buffer.append(HttpHeaders.PROXY_AUTHORIZATION);
|
|
||||||
} else {
|
|
||||||
buffer.append(HttpHeaders.AUTHORIZATION);
|
|
||||||
}
|
|
||||||
buffer.append(": NTLM ");
|
|
||||||
buffer.append(response);
|
|
||||||
return new BufferedHeader(buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isComplete() {
|
public boolean isChallengeComplete() {
|
||||||
return this.state == State.MSG_TYPE3_GENERATED || this.state == State.FAILED;
|
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;
|
package org.apache.http.impl.auth;
|
||||||
|
|
||||||
import org.apache.http.annotation.NotThreadSafe;
|
import org.apache.http.annotation.NotThreadSafe;
|
||||||
import org.apache.http.auth.Credentials;
|
|
||||||
import org.ietf.jgss.GSSException;
|
import org.ietf.jgss.GSSException;
|
||||||
import org.ietf.jgss.Oid;
|
import org.ietf.jgss.Oid;
|
||||||
|
|
||||||
@ -58,13 +57,13 @@ public SPNegoScheme() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSchemeName() {
|
public String getName() {
|
||||||
return "Negotiate";
|
return "Negotiate";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected byte[] generateToken(final byte[] input, final String authServer, final Credentials credentials) throws GSSException {
|
protected byte[] generateToken(final byte[] input, final String authServer) throws GSSException {
|
||||||
return generateGSSToken(input, new Oid(SPNEGO_OID), authServer, credentials);
|
return generateGSSToken(input, new Oid(SPNEGO_OID), authServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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.annotation.Immutable;
|
import org.apache.http.annotation.Immutable;
|
||||||
import org.apache.http.auth.AuthScheme;
|
import org.apache.http.auth.AuthScheme;
|
||||||
import org.apache.http.auth.AuthState;
|
import org.apache.http.auth.AuthState;
|
||||||
import org.apache.http.auth.Credentials;
|
|
||||||
import org.apache.http.client.UserTokenHandler;
|
import org.apache.http.client.UserTokenHandler;
|
||||||
import org.apache.http.client.protocol.HttpClientContext;
|
import org.apache.http.client.protocol.HttpClientContext;
|
||||||
import org.apache.http.conn.ManagedHttpClientConnection;
|
import org.apache.http.conn.ManagedHttpClientConnection;
|
||||||
@ -90,11 +89,8 @@ public Object getUserToken(final HttpContext context) {
|
|||||||
|
|
||||||
private static Principal getAuthPrincipal(final AuthState authState) {
|
private static Principal getAuthPrincipal(final AuthState authState) {
|
||||||
final AuthScheme scheme = authState.getAuthScheme();
|
final AuthScheme scheme = authState.getAuthScheme();
|
||||||
if (scheme != null && scheme.isComplete() && scheme.isConnectionBased()) {
|
if (scheme != null && scheme.isConnectionBased()) {
|
||||||
final Credentials creds = authState.getCredentials();
|
return scheme.getPrinciple();
|
||||||
if (creds != null) {
|
|
||||||
return creds.getUserPrincipal();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -177,7 +177,7 @@ public Socket tunnel(
|
|||||||
conn.bind(socket);
|
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);
|
response = this.requestExec.execute(connect, conn, context);
|
||||||
|
|
||||||
|
@ -248,13 +248,15 @@ public CloseableHttpResponse execute(
|
|||||||
if (this.log.isDebugEnabled()) {
|
if (this.log.isDebugEnabled()) {
|
||||||
this.log.debug("Target auth state: " + targetAuthState.getState());
|
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 (!request.containsHeader(HttpHeaders.PROXY_AUTHORIZATION) && !route.isTunnelled()) {
|
||||||
if (this.log.isDebugEnabled()) {
|
if (this.log.isDebugEnabled()) {
|
||||||
this.log.debug("Proxy auth state: " + proxyAuthState.getState());
|
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);
|
response = requestExecutor.execute(request, managedConn, context);
|
||||||
@ -423,7 +425,7 @@ void establishRoute(
|
|||||||
* The connection must be established to the (last) proxy.
|
* The connection must be established to the (last) proxy.
|
||||||
* A CONNECT request for tunnelling through the proxy will
|
* A CONNECT request for tunnelling through the proxy will
|
||||||
* be created and sent, the response received and checked.
|
* 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.
|
* information about the tunnel, that is left to the caller.
|
||||||
*/
|
*/
|
||||||
private boolean createTunnelToTarget(
|
private boolean createTunnelToTarget(
|
||||||
@ -455,7 +457,7 @@ private boolean createTunnelToTarget(
|
|||||||
}
|
}
|
||||||
|
|
||||||
connect.removeHeaders(HttpHeaders.PROXY_AUTHORIZATION);
|
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);
|
response = this.requestExecutor.execute(connect, managedConn, context);
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
* Request executor in the request execution chain that is responsible
|
* Request executor in the request execution chain that is responsible
|
||||||
* for implementation of HTTP specification requirements.
|
* for implementation of HTTP specification requirements.
|
||||||
* Internally this executor relies on a {@link HttpProcessor} to populate
|
* 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}.
|
* session state in {@link HttpClientContext}.
|
||||||
* <p>
|
* <p>
|
||||||
* Further responsibilities such as communication with the opposite
|
* Further responsibilities such as communication with the opposite
|
||||||
|
@ -113,9 +113,7 @@ public void testPreemptiveTargetAndProxyAuth() throws Exception {
|
|||||||
final HttpRequestInterceptor interceptor = new RequestAuthCache();
|
final HttpRequestInterceptor interceptor = new RequestAuthCache();
|
||||||
interceptor.process(request, context);
|
interceptor.process(request, context);
|
||||||
Assert.assertNotNull(this.targetState.getAuthScheme());
|
Assert.assertNotNull(this.targetState.getAuthScheme());
|
||||||
Assert.assertSame(this.creds1, this.targetState.getCredentials());
|
|
||||||
Assert.assertNotNull(this.proxyState.getAuthScheme());
|
Assert.assertNotNull(this.proxyState.getAuthScheme());
|
||||||
Assert.assertSame(this.creds2, this.proxyState.getCredentials());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -138,9 +136,7 @@ public void testCredentialsProviderNotSet() throws Exception {
|
|||||||
final HttpRequestInterceptor interceptor = new RequestAuthCache();
|
final HttpRequestInterceptor interceptor = new RequestAuthCache();
|
||||||
interceptor.process(request, context);
|
interceptor.process(request, context);
|
||||||
Assert.assertNull(this.targetState.getAuthScheme());
|
Assert.assertNull(this.targetState.getAuthScheme());
|
||||||
Assert.assertNull(this.targetState.getCredentials());
|
|
||||||
Assert.assertNull(this.proxyState.getAuthScheme());
|
Assert.assertNull(this.proxyState.getAuthScheme());
|
||||||
Assert.assertNull(this.proxyState.getCredentials());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -158,9 +154,7 @@ public void testAuthCacheNotSet() throws Exception {
|
|||||||
final HttpRequestInterceptor interceptor = new RequestAuthCache();
|
final HttpRequestInterceptor interceptor = new RequestAuthCache();
|
||||||
interceptor.process(request, context);
|
interceptor.process(request, context);
|
||||||
Assert.assertNull(this.targetState.getAuthScheme());
|
Assert.assertNull(this.targetState.getAuthScheme());
|
||||||
Assert.assertNull(this.targetState.getCredentials());
|
|
||||||
Assert.assertNull(this.proxyState.getAuthScheme());
|
Assert.assertNull(this.proxyState.getAuthScheme());
|
||||||
Assert.assertNull(this.proxyState.getCredentials());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -180,36 +174,7 @@ public void testAuthCacheEmpty() throws Exception {
|
|||||||
final HttpRequestInterceptor interceptor = new RequestAuthCache();
|
final HttpRequestInterceptor interceptor = new RequestAuthCache();
|
||||||
interceptor.process(request, context);
|
interceptor.process(request, context);
|
||||||
Assert.assertNull(this.targetState.getAuthScheme());
|
Assert.assertNull(this.targetState.getAuthScheme());
|
||||||
Assert.assertNull(this.targetState.getCredentials());
|
|
||||||
Assert.assertNull(this.proxyState.getAuthScheme());
|
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
|
@Test
|
||||||
@ -230,16 +195,14 @@ public void testAuthSchemeAlreadySet() throws Exception {
|
|||||||
context.setAttribute(HttpClientContext.AUTH_CACHE, authCache);
|
context.setAttribute(HttpClientContext.AUTH_CACHE, authCache);
|
||||||
|
|
||||||
this.targetState.setState(AuthProtocolState.CHALLENGED);
|
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.setState(AuthProtocolState.CHALLENGED);
|
||||||
this.proxyState.update(new BasicScheme(), new UsernamePasswordCredentials("user4", "secret4"));
|
this.proxyState.update(new BasicScheme());
|
||||||
|
|
||||||
final HttpRequestInterceptor interceptor = new RequestAuthCache();
|
final HttpRequestInterceptor interceptor = new RequestAuthCache();
|
||||||
interceptor.process(request, context);
|
interceptor.process(request, context);
|
||||||
Assert.assertNotSame(this.authscheme1, this.targetState.getAuthScheme());
|
Assert.assertNotSame(this.authscheme1, this.targetState.getAuthScheme());
|
||||||
Assert.assertNotSame(this.creds1, this.targetState.getCredentials());
|
|
||||||
Assert.assertNotSame(this.authscheme2, this.proxyState.getAuthScheme());
|
Assert.assertNotSame(this.authscheme2, this.proxyState.getAuthScheme());
|
||||||
Assert.assertNotSame(this.creds2, this.proxyState.getCredentials());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -34,17 +34,15 @@
|
|||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import org.apache.http.Consts;
|
import org.apache.http.Consts;
|
||||||
import org.apache.http.Header;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.HttpHeaders;
|
|
||||||
import org.apache.http.HttpRequest;
|
import org.apache.http.HttpRequest;
|
||||||
import org.apache.http.auth.AuthChallenge;
|
import org.apache.http.auth.AuthChallenge;
|
||||||
import org.apache.http.auth.AuthScheme;
|
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.auth.UsernamePasswordCredentials;
|
||||||
|
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||||
import org.apache.http.message.BasicHttpRequest;
|
import org.apache.http.message.BasicHttpRequest;
|
||||||
import org.apache.http.message.ParserCursor;
|
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.CharArrayBuffer;
|
||||||
import org.apache.http.util.EncodingUtils;
|
import org.apache.http.util.EncodingUtils;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
@ -69,7 +67,7 @@ public void testBasicAuthenticationEmptyChallenge() throws Exception {
|
|||||||
final String challenge = "Basic";
|
final String challenge = "Basic";
|
||||||
final AuthChallenge authChallenge = parse(challenge);
|
final AuthChallenge authChallenge = parse(challenge);
|
||||||
final AuthScheme authscheme = new BasicScheme();
|
final AuthScheme authscheme = new BasicScheme();
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
authscheme.processChallenge(authChallenge, null);
|
||||||
Assert.assertNull(authscheme.getRealm());
|
Assert.assertNull(authscheme.getRealm());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,56 +79,66 @@ public void testBasicAuthenticationWith88591Chars() throws Exception {
|
|||||||
buffer.append((char)germanChar);
|
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 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);
|
final BasicScheme authscheme = new BasicScheme(Consts.ISO_8859_1);
|
||||||
|
|
||||||
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||||
final HttpContext context = new BasicHttpContext();
|
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||||
final Header header = authscheme.authenticate(creds, request, context);
|
Assert.assertEquals("Basic ZGg65C32Lfw=", authResponse);
|
||||||
Assert.assertEquals("Basic ZGg65C32Lfw=", header.getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBasicAuthentication() throws Exception {
|
public void testBasicAuthentication() throws Exception {
|
||||||
final UsernamePasswordCredentials creds = new UsernamePasswordCredentials("testuser", "testpass");
|
|
||||||
|
|
||||||
final AuthChallenge authChallenge = parse("Basic realm=\"test\"");
|
final AuthChallenge authChallenge = parse("Basic realm=\"test\"");
|
||||||
|
|
||||||
final BasicScheme authscheme = new BasicScheme();
|
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 HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||||
final HttpContext context = new BasicHttpContext();
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
final Header authResponse = authscheme.authenticate(creds, request, context);
|
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||||
|
|
||||||
final String expected = "Basic " + EncodingUtils.getAsciiString(
|
final String expected = "Basic " + EncodingUtils.getAsciiString(
|
||||||
Base64.encodeBase64(EncodingUtils.getAsciiBytes("testuser:testpass")));
|
Base64.encodeBase64(EncodingUtils.getAsciiBytes("testuser:testpass")));
|
||||||
Assert.assertEquals(HttpHeaders.AUTHORIZATION, authResponse.getName());
|
Assert.assertEquals(expected, authResponse);
|
||||||
Assert.assertEquals(expected, authResponse.getValue());
|
|
||||||
Assert.assertEquals("test", authscheme.getRealm());
|
Assert.assertEquals("test", authscheme.getRealm());
|
||||||
Assert.assertTrue(authscheme.isComplete());
|
Assert.assertTrue(authscheme.isChallengeComplete());
|
||||||
Assert.assertFalse(authscheme.isConnectionBased());
|
Assert.assertFalse(authscheme.isConnectionBased());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBasicProxyAuthentication() throws Exception {
|
public void testBasicProxyAuthentication() throws Exception {
|
||||||
final UsernamePasswordCredentials creds = new UsernamePasswordCredentials("testuser", "testpass");
|
|
||||||
|
|
||||||
final AuthChallenge authChallenge = parse("Basic realm=\"test\"");
|
final AuthChallenge authChallenge = parse("Basic realm=\"test\"");
|
||||||
|
|
||||||
final BasicScheme authscheme = new BasicScheme();
|
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 HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||||
final HttpContext context = new BasicHttpContext();
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
final Header authResponse = authscheme.authenticate(creds, request, context);
|
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||||
|
|
||||||
final String expected = "Basic " + EncodingUtils.getAsciiString(
|
final String expected = "Basic " + EncodingUtils.getAsciiString(
|
||||||
Base64.encodeBase64(EncodingUtils.getAsciiBytes("testuser:testpass")));
|
Base64.encodeBase64(EncodingUtils.getAsciiBytes("testuser:testpass")));
|
||||||
Assert.assertEquals(HttpHeaders.PROXY_AUTHORIZATION, authResponse.getName());
|
Assert.assertEquals(expected, authResponse);
|
||||||
Assert.assertEquals(expected, authResponse.getValue());
|
|
||||||
Assert.assertEquals("test", authscheme.getRealm());
|
Assert.assertEquals("test", authscheme.getRealm());
|
||||||
Assert.assertTrue(authscheme.isComplete());
|
Assert.assertTrue(authscheme.isChallengeComplete());
|
||||||
Assert.assertFalse(authscheme.isConnectionBased());
|
Assert.assertFalse(authscheme.isConnectionBased());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +147,7 @@ public void testSerialization() throws Exception {
|
|||||||
final AuthChallenge authChallenge = parse("Basic realm=\"test\"");
|
final AuthChallenge authChallenge = parse("Basic realm=\"test\"");
|
||||||
|
|
||||||
final BasicScheme basicScheme = new BasicScheme();
|
final BasicScheme basicScheme = new BasicScheme();
|
||||||
basicScheme.processChallenge(ChallengeType.PROXY, authChallenge);
|
basicScheme.processChallenge(authChallenge, null);
|
||||||
|
|
||||||
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
final ObjectOutputStream out = new ObjectOutputStream(buffer);
|
final ObjectOutputStream out = new ObjectOutputStream(buffer);
|
||||||
@ -149,10 +157,9 @@ public void testSerialization() throws Exception {
|
|||||||
final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(raw));
|
final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(raw));
|
||||||
final BasicScheme authScheme = (BasicScheme) in.readObject();
|
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.getRealm(), authScheme.getRealm());
|
||||||
Assert.assertEquals(basicScheme.isComplete(), authScheme.isComplete());
|
Assert.assertEquals(basicScheme.isChallengeComplete(), authScheme.isChallengeComplete());
|
||||||
Assert.assertEquals(true, basicScheme.isProxy());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -167,10 +174,9 @@ public void testSerializationUnchallenged() throws Exception {
|
|||||||
final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(raw));
|
final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(raw));
|
||||||
final BasicScheme authScheme = (BasicScheme) in.readObject();
|
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.getRealm(), authScheme.getRealm());
|
||||||
Assert.assertEquals(basicScheme.isComplete(), authScheme.isComplete());
|
Assert.assertEquals(basicScheme.isChallengeComplete(), authScheme.isChallengeComplete());
|
||||||
Assert.assertEquals(false, basicScheme.isProxy());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,26 +36,25 @@
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
|
||||||
import org.apache.http.HeaderElement;
|
import org.apache.http.HeaderElement;
|
||||||
import org.apache.http.HttpEntityEnclosingRequest;
|
import org.apache.http.HttpEntityEnclosingRequest;
|
||||||
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.HttpRequest;
|
import org.apache.http.HttpRequest;
|
||||||
import org.apache.http.auth.AuthChallenge;
|
import org.apache.http.auth.AuthChallenge;
|
||||||
import org.apache.http.auth.AuthScheme;
|
import org.apache.http.auth.AuthScheme;
|
||||||
|
import org.apache.http.auth.AuthScope;
|
||||||
import org.apache.http.auth.AuthenticationException;
|
import org.apache.http.auth.AuthenticationException;
|
||||||
import org.apache.http.auth.ChallengeType;
|
|
||||||
import org.apache.http.auth.Credentials;
|
import org.apache.http.auth.Credentials;
|
||||||
import org.apache.http.auth.MalformedChallengeException;
|
import org.apache.http.auth.MalformedChallengeException;
|
||||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||||
import org.apache.http.entity.InputStreamEntity;
|
import org.apache.http.entity.InputStreamEntity;
|
||||||
import org.apache.http.entity.StringEntity;
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||||
import org.apache.http.message.BasicHeaderValueParser;
|
import org.apache.http.message.BasicHeaderValueParser;
|
||||||
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
|
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
|
||||||
import org.apache.http.message.BasicHttpRequest;
|
import org.apache.http.message.BasicHttpRequest;
|
||||||
import org.apache.http.message.ParserCursor;
|
import org.apache.http.message.ParserCursor;
|
||||||
import org.apache.http.protocol.BasicHttpContext;
|
|
||||||
import org.apache.http.protocol.HTTP;
|
import org.apache.http.protocol.HTTP;
|
||||||
import org.apache.http.protocol.HttpContext;
|
|
||||||
import org.apache.http.util.CharArrayBuffer;
|
import org.apache.http.util.CharArrayBuffer;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -78,27 +77,33 @@ private static AuthChallenge parse(final String s) {
|
|||||||
public void testDigestAuthenticationEmptyChallenge1() throws Exception {
|
public void testDigestAuthenticationEmptyChallenge1() throws Exception {
|
||||||
final AuthChallenge authChallenge = parse("Digest");
|
final AuthChallenge authChallenge = parse("Digest");
|
||||||
final AuthScheme authscheme = new DigestScheme();
|
final AuthScheme authscheme = new DigestScheme();
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
authscheme.processChallenge(authChallenge, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected=MalformedChallengeException.class)
|
@Test(expected=MalformedChallengeException.class)
|
||||||
public void testDigestAuthenticationEmptyChallenge2() throws Exception {
|
public void testDigestAuthenticationEmptyChallenge2() throws Exception {
|
||||||
final AuthChallenge authChallenge = parse("Digest ");
|
final AuthChallenge authChallenge = parse("Digest ");
|
||||||
final AuthScheme authscheme = new DigestScheme();
|
final AuthScheme authscheme = new DigestScheme();
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
authscheme.processChallenge(authChallenge, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDigestAuthenticationWithDefaultCreds() throws Exception {
|
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 String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
|
||||||
final AuthChallenge authChallenge = parse(challenge);
|
final AuthChallenge authChallenge = parse(challenge);
|
||||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
|
||||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
|
||||||
final DigestScheme authscheme = new DigestScheme();
|
final DigestScheme authscheme = new DigestScheme();
|
||||||
final HttpContext context = new BasicHttpContext();
|
authscheme.processChallenge(authChallenge, null);
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
|
||||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
Assert.assertTrue(authscheme.isComplete());
|
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||||
|
Assert.assertTrue(authscheme.isChallengeComplete());
|
||||||
Assert.assertFalse(authscheme.isConnectionBased());
|
Assert.assertFalse(authscheme.isConnectionBased());
|
||||||
|
|
||||||
final Map<String, String> table = parseAuthResponse(authResponse);
|
final Map<String, String> table = parseAuthResponse(authResponse);
|
||||||
@ -111,14 +116,20 @@ public void testDigestAuthenticationWithDefaultCreds() throws Exception {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDigestAuthentication() throws Exception {
|
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 String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
|
||||||
final AuthChallenge authChallenge = parse(challenge);
|
final AuthChallenge authChallenge = parse(challenge);
|
||||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
|
||||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
|
||||||
final DigestScheme authscheme = new DigestScheme();
|
final DigestScheme authscheme = new DigestScheme();
|
||||||
final HttpContext context = new BasicHttpContext();
|
authscheme.processChallenge(authChallenge, null);
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
|
||||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
|
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||||
|
|
||||||
final Map<String, String> table = parseAuthResponse(authResponse);
|
final Map<String, String> table = parseAuthResponse(authResponse);
|
||||||
Assert.assertEquals("username", table.get("username"));
|
Assert.assertEquals("username", table.get("username"));
|
||||||
@ -130,20 +141,29 @@ public void testDigestAuthentication() throws Exception {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDigestAuthenticationInvalidInput() throws Exception {
|
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 String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
|
||||||
final AuthChallenge authChallenge = parse(challenge);
|
final AuthChallenge authChallenge = parse(challenge);
|
||||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
|
||||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
|
||||||
final DigestScheme authscheme = new DigestScheme();
|
final DigestScheme authscheme = new DigestScheme();
|
||||||
final HttpContext context = new BasicHttpContext();
|
authscheme.processChallenge(authChallenge, null);
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
|
||||||
try {
|
try {
|
||||||
authscheme.authenticate(null, request, context);
|
authscheme.isResponseReady(null, credentialsProvider, null);
|
||||||
Assert.fail("IllegalArgumentException should have been thrown");
|
Assert.fail("IllegalArgumentException should have been thrown");
|
||||||
} catch (final IllegalArgumentException ex) {
|
} catch (final IllegalArgumentException ex) {
|
||||||
}
|
}
|
||||||
try {
|
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");
|
Assert.fail("IllegalArgumentException should have been thrown");
|
||||||
} catch (final IllegalArgumentException ex) {
|
} catch (final IllegalArgumentException ex) {
|
||||||
}
|
}
|
||||||
@ -151,16 +171,22 @@ public void testDigestAuthenticationInvalidInput() throws Exception {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDigestAuthenticationWithSHA() throws Exception {
|
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\", " +
|
final String challenge = "Digest realm=\"realm1\", " +
|
||||||
"nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
|
"nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
|
||||||
"algorithm=SHA";
|
"algorithm=SHA";
|
||||||
final AuthChallenge authChallenge = parse(challenge);
|
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();
|
final DigestScheme authscheme = new DigestScheme();
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
authscheme.processChallenge(authChallenge, null);
|
||||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
|
||||||
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
|
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||||
|
|
||||||
final Map<String, String> table = parseAuthResponse(authResponse);
|
final Map<String, String> table = parseAuthResponse(authResponse);
|
||||||
Assert.assertEquals("username", table.get("username"));
|
Assert.assertEquals("username", table.get("username"));
|
||||||
@ -172,14 +198,20 @@ public void testDigestAuthenticationWithSHA() throws Exception {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDigestAuthenticationWithQueryStringInDigestURI() throws Exception {
|
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 String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
|
||||||
final AuthChallenge authChallenge = parse(challenge);
|
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();
|
final DigestScheme authscheme = new DigestScheme();
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
authscheme.processChallenge(authChallenge, null);
|
||||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
|
||||||
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
|
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||||
|
|
||||||
final Map<String, String> table = parseAuthResponse(authResponse);
|
final Map<String, String> table = parseAuthResponse(authResponse);
|
||||||
Assert.assertEquals("username", table.get("username"));
|
Assert.assertEquals("username", table.get("username"));
|
||||||
@ -189,64 +221,40 @@ public void testDigestAuthenticationWithQueryStringInDigestURI() throws Exceptio
|
|||||||
Assert.assertEquals("a847f58f5fef0bc087bcb9c3eb30e042", table.get("response"));
|
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)
|
@Test(expected=AuthenticationException.class)
|
||||||
public void testDigestAuthenticationNoRealm() throws Exception {
|
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 String challenge = "Digest no-realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
|
||||||
final AuthChallenge authChallenge = parse(challenge);
|
final AuthChallenge authChallenge = parse(challenge);
|
||||||
final HttpContext context = new BasicHttpContext();
|
|
||||||
final DigestScheme authscheme = new DigestScheme();
|
final DigestScheme authscheme = new DigestScheme();
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
authscheme.processChallenge(authChallenge, null);
|
||||||
|
|
||||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
authscheme.generateAuthResponse(host, request, null);
|
||||||
authscheme.authenticate(cred, request, context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected=AuthenticationException.class)
|
@Test(expected=AuthenticationException.class)
|
||||||
public void testDigestAuthenticationNoNonce() throws Exception {
|
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 String challenge = "Digest realm=\"realm1\", no-nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
|
||||||
final AuthChallenge authChallenge = parse(challenge);
|
final AuthChallenge authChallenge = parse(challenge);
|
||||||
final HttpContext context = new BasicHttpContext();
|
|
||||||
final DigestScheme authscheme = new DigestScheme();
|
final DigestScheme authscheme = new DigestScheme();
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
authscheme.processChallenge(authChallenge, null);
|
||||||
|
|
||||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
authscheme.generateAuthResponse(host, request, null);
|
||||||
authscheme.authenticate(cred, request, context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -261,6 +269,13 @@ public void testDigestAuthenticationMD5Sess() throws Exception {
|
|||||||
final String password="password";
|
final String password="password";
|
||||||
final String nonce="e273f1776275974f1a120d8b92c5b3cb";
|
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 + "\", "
|
final String challenge="Digest realm=\"" + realm + "\", "
|
||||||
+ "nonce=\"" + nonce + "\", "
|
+ "nonce=\"" + nonce + "\", "
|
||||||
+ "opaque=\"SomeString\", "
|
+ "opaque=\"SomeString\", "
|
||||||
@ -270,17 +285,14 @@ public void testDigestAuthenticationMD5Sess() throws Exception {
|
|||||||
|
|
||||||
final AuthChallenge authChallenge = parse(challenge);
|
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();
|
final DigestScheme authscheme = new DigestScheme();
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
authscheme.processChallenge(authChallenge, null);
|
||||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
|
||||||
final String response = authResponse.getValue();
|
|
||||||
|
|
||||||
Assert.assertTrue(response.indexOf("nc=00000001") > 0); // test for quotes
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
Assert.assertTrue(response.indexOf("qop=auth") > 0); // test for quotes
|
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);
|
final Map<String, String> table = parseAuthResponse(authResponse);
|
||||||
Assert.assertEquals(username, table.get("username"));
|
Assert.assertEquals(username, table.get("username"));
|
||||||
@ -308,6 +320,13 @@ public void testDigestAuthenticationMD5SessNoQop() throws Exception {
|
|||||||
final String password="password";
|
final String password="password";
|
||||||
final String nonce="e273f1776275974f1a120d8b92c5b3cb";
|
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 + "\", "
|
final String challenge="Digest realm=\"" + realm + "\", "
|
||||||
+ "nonce=\"" + nonce + "\", "
|
+ "nonce=\"" + nonce + "\", "
|
||||||
+ "opaque=\"SomeString\", "
|
+ "opaque=\"SomeString\", "
|
||||||
@ -316,14 +335,10 @@ public void testDigestAuthenticationMD5SessNoQop() throws Exception {
|
|||||||
|
|
||||||
final AuthChallenge authChallenge = parse(challenge);
|
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();
|
final DigestScheme authscheme = new DigestScheme();
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
authscheme.processChallenge(authChallenge, null);
|
||||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
|
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||||
|
|
||||||
final Map<String, String> table = parseAuthResponse(authResponse);
|
final Map<String, String> table = parseAuthResponse(authResponse);
|
||||||
Assert.assertEquals(username, table.get("username"));
|
Assert.assertEquals(username, table.get("username"));
|
||||||
@ -350,6 +365,13 @@ public void testDigestAuthenticationMD5SessUnknownQop() throws Exception {
|
|||||||
final String password="password";
|
final String password="password";
|
||||||
final String nonce="e273f1776275974f1a120d8b92c5b3cb";
|
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 + "\", "
|
final String challenge="Digest realm=\"" + realm + "\", "
|
||||||
+ "nonce=\"" + nonce + "\", "
|
+ "nonce=\"" + nonce + "\", "
|
||||||
+ "opaque=\"SomeString\", "
|
+ "opaque=\"SomeString\", "
|
||||||
@ -360,12 +382,10 @@ public void testDigestAuthenticationMD5SessUnknownQop() throws Exception {
|
|||||||
final AuthChallenge authChallenge = parse(challenge);
|
final AuthChallenge authChallenge = parse(challenge);
|
||||||
|
|
||||||
final DigestScheme authscheme = new DigestScheme();
|
final DigestScheme authscheme = new DigestScheme();
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
authscheme.processChallenge(authChallenge, null);
|
||||||
|
|
||||||
final Credentials cred = new UsernamePasswordCredentials(username, password);
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
authscheme.generateAuthResponse(host, request, null);
|
||||||
final HttpContext context = new BasicHttpContext();
|
|
||||||
authscheme.authenticate(cred, request, context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -380,6 +400,13 @@ public void testDigestAuthenticationUnknownAlgo() throws Exception {
|
|||||||
final String password="password";
|
final String password="password";
|
||||||
final String nonce="e273f1776275974f1a120d8b92c5b3cb";
|
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 + "\", "
|
final String challenge="Digest realm=\"" + realm + "\", "
|
||||||
+ "nonce=\"" + nonce + "\", "
|
+ "nonce=\"" + nonce + "\", "
|
||||||
+ "opaque=\"SomeString\", "
|
+ "opaque=\"SomeString\", "
|
||||||
@ -390,12 +417,10 @@ public void testDigestAuthenticationUnknownAlgo() throws Exception {
|
|||||||
final AuthChallenge authChallenge = parse(challenge);
|
final AuthChallenge authChallenge = parse(challenge);
|
||||||
|
|
||||||
final DigestScheme authscheme = new DigestScheme();
|
final DigestScheme authscheme = new DigestScheme();
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
authscheme.processChallenge(authChallenge, null);
|
||||||
|
|
||||||
final Credentials cred = new UsernamePasswordCredentials(username, password);
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
final HttpRequest request = new BasicHttpRequest("Simple", "/");
|
authscheme.generateAuthResponse(host, request, null);
|
||||||
final HttpContext context = new BasicHttpContext();
|
|
||||||
authscheme.authenticate(cred, request, context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -404,17 +429,16 @@ public void testDigestAuthenticationWithStaleNonce() throws Exception {
|
|||||||
"nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", stale=\"true\"";
|
"nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", stale=\"true\"";
|
||||||
final AuthChallenge authChallenge = parse(challenge);
|
final AuthChallenge authChallenge = parse(challenge);
|
||||||
final AuthScheme authscheme = new DigestScheme();
|
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) {
|
private static Map<String, String> parseAuthResponse(final String authResponse) {
|
||||||
final String s = authResponse.getValue();
|
if (!authResponse.startsWith("Digest ")) {
|
||||||
if (!s.startsWith("Digest ")) {
|
|
||||||
return null;
|
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);
|
final Map<String, String> map = new HashMap<>(elements.length);
|
||||||
for (final HeaderElement element : elements) {
|
for (final HeaderElement element : elements) {
|
||||||
map.put(element.getName(), element.getValue());
|
map.put(element.getName(), element.getValue());
|
||||||
@ -424,50 +448,73 @@ private static Map<String, String> parseAuthResponse(final Header authResponse)
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDigestNouceCount() throws Exception {
|
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 String challenge1 = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", qop=auth";
|
||||||
final AuthChallenge authChallenge1 = parse(challenge1);
|
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();
|
final DigestScheme authscheme = new DigestScheme();
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge1);
|
authscheme.processChallenge(authChallenge1, null);
|
||||||
final Header authResponse1 = authscheme.authenticate(cred, request, context);
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
|
final String authResponse1 = authscheme.generateAuthResponse(host, request, null);
|
||||||
|
|
||||||
final Map<String, String> table1 = parseAuthResponse(authResponse1);
|
final Map<String, String> table1 = parseAuthResponse(authResponse1);
|
||||||
Assert.assertEquals("00000001", table1.get("nc"));
|
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);
|
final Map<String, String> table2 = parseAuthResponse(authResponse2);
|
||||||
Assert.assertEquals("00000002", table2.get("nc"));
|
Assert.assertEquals("00000002", table2.get("nc"));
|
||||||
final String challenge2 = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", qop=auth";
|
final String challenge2 = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", qop=auth";
|
||||||
final AuthChallenge authChallenge2 = parse(challenge2);
|
final AuthChallenge authChallenge2 = parse(challenge2);
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge2);
|
authscheme.processChallenge(authChallenge2, null);
|
||||||
final Header authResponse3 = authscheme.authenticate(cred, request, context);
|
|
||||||
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
|
final String authResponse3 = authscheme.generateAuthResponse(host, request, null);
|
||||||
|
|
||||||
final Map<String, String> table3 = parseAuthResponse(authResponse3);
|
final Map<String, String> table3 = parseAuthResponse(authResponse3);
|
||||||
Assert.assertEquals("00000003", table3.get("nc"));
|
Assert.assertEquals("00000003", table3.get("nc"));
|
||||||
final String challenge3 = "Digest realm=\"realm1\", nonce=\"e273f1776275974f1a120d8b92c5b3cb\", qop=auth";
|
final String challenge3 = "Digest realm=\"realm1\", nonce=\"e273f1776275974f1a120d8b92c5b3cb\", qop=auth";
|
||||||
final AuthChallenge authChallenge3 = parse(challenge3);
|
final AuthChallenge authChallenge3 = parse(challenge3);
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge3);
|
authscheme.processChallenge(authChallenge3, null);
|
||||||
final Header authResponse4 = authscheme.authenticate(cred, request, context);
|
|
||||||
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
|
final String authResponse4 = authscheme.generateAuthResponse(host, request, null);
|
||||||
|
|
||||||
final Map<String, String> table4 = parseAuthResponse(authResponse4);
|
final Map<String, String> table4 = parseAuthResponse(authResponse4);
|
||||||
Assert.assertEquals("00000001", table4.get("nc"));
|
Assert.assertEquals("00000001", table4.get("nc"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDigestMD5SessA1AndCnonceConsistency() throws Exception {
|
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\", " +
|
final String challenge1 = "Digest qop=\"auth\", algorithm=MD5-sess, nonce=\"1234567890abcdef\", " +
|
||||||
"charset=utf-8, realm=\"subnet.domain.com\"";
|
"charset=utf-8, realm=\"subnet.domain.com\"";
|
||||||
final AuthChallenge authChallenge1 = parse(challenge1);
|
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();
|
final DigestScheme authscheme = new DigestScheme();
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge1);
|
authscheme.processChallenge(authChallenge1, null);
|
||||||
final Header authResponse1 = authscheme.authenticate(cred, request, context);
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
|
final String authResponse1 = authscheme.generateAuthResponse(host, request, null);
|
||||||
|
|
||||||
final Map<String, String> table1 = parseAuthResponse(authResponse1);
|
final Map<String, String> table1 = parseAuthResponse(authResponse1);
|
||||||
Assert.assertEquals("00000001", table1.get("nc"));
|
Assert.assertEquals("00000001", table1.get("nc"));
|
||||||
final String cnonce1 = authscheme.getCnonce();
|
final String cnonce1 = authscheme.getCnonce();
|
||||||
final String sessionKey1 = authscheme.getA1();
|
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);
|
final Map<String, String> table2 = parseAuthResponse(authResponse2);
|
||||||
Assert.assertEquals("00000002", table2.get("nc"));
|
Assert.assertEquals("00000002", table2.get("nc"));
|
||||||
final String cnonce2 = authscheme.getCnonce();
|
final String cnonce2 = authscheme.getCnonce();
|
||||||
@ -479,8 +526,9 @@ public void testDigestMD5SessA1AndCnonceConsistency() throws Exception {
|
|||||||
final String challenge2 = "Digest qop=\"auth\", algorithm=MD5-sess, nonce=\"1234567890abcdef\", " +
|
final String challenge2 = "Digest qop=\"auth\", algorithm=MD5-sess, nonce=\"1234567890abcdef\", " +
|
||||||
"charset=utf-8, realm=\"subnet.domain.com\"";
|
"charset=utf-8, realm=\"subnet.domain.com\"";
|
||||||
final AuthChallenge authChallenge2 = parse(challenge2);
|
final AuthChallenge authChallenge2 = parse(challenge2);
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge2);
|
authscheme.processChallenge(authChallenge2, null);
|
||||||
final Header authResponse3 = authscheme.authenticate(cred, request, context);
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
|
final String authResponse3 = authscheme.generateAuthResponse(host, request, null);
|
||||||
final Map<String, String> table3 = parseAuthResponse(authResponse3);
|
final Map<String, String> table3 = parseAuthResponse(authResponse3);
|
||||||
Assert.assertEquals("00000003", table3.get("nc"));
|
Assert.assertEquals("00000003", table3.get("nc"));
|
||||||
|
|
||||||
@ -493,8 +541,9 @@ public void testDigestMD5SessA1AndCnonceConsistency() throws Exception {
|
|||||||
final String challenge3 = "Digest qop=\"auth\", algorithm=MD5-sess, nonce=\"fedcba0987654321\", " +
|
final String challenge3 = "Digest qop=\"auth\", algorithm=MD5-sess, nonce=\"fedcba0987654321\", " +
|
||||||
"charset=utf-8, realm=\"subnet.domain.com\"";
|
"charset=utf-8, realm=\"subnet.domain.com\"";
|
||||||
final AuthChallenge authChallenge3 = parse(challenge3);
|
final AuthChallenge authChallenge3 = parse(challenge3);
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge3);
|
authscheme.processChallenge(authChallenge3, null);
|
||||||
final Header authResponse4 = authscheme.authenticate(cred, request, context);
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
|
final String authResponse4 = authscheme.generateAuthResponse(host, request, null);
|
||||||
final Map<String, String> table4 = parseAuthResponse(authResponse4);
|
final Map<String, String> table4 = parseAuthResponse(authResponse4);
|
||||||
Assert.assertEquals("00000001", table4.get("nc"));
|
Assert.assertEquals("00000001", table4.get("nc"));
|
||||||
|
|
||||||
@ -533,16 +582,21 @@ public void testHttpEntityDigest() throws Exception {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDigestAuthenticationQopAuthInt() throws Exception {
|
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\", " +
|
final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
|
||||||
"qop=\"auth,auth-int\"";
|
"qop=\"auth,auth-int\"";
|
||||||
final AuthChallenge authChallenge = parse(challenge);
|
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 DigestScheme authscheme = new DigestScheme();
|
||||||
final HttpContext context = new BasicHttpContext();
|
authscheme.processChallenge(authChallenge, null);
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||||
|
|
||||||
Assert.assertEquals("Post:/:acd2b59cd01c7737d8069015584c6cac", authscheme.getA2());
|
Assert.assertEquals("Post:/:acd2b59cd01c7737d8069015584c6cac", authscheme.getA2());
|
||||||
|
|
||||||
@ -556,15 +610,20 @@ public void testDigestAuthenticationQopAuthInt() throws Exception {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDigestAuthenticationQopAuthIntNullEntity() throws Exception {
|
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\", " +
|
final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
|
||||||
"qop=\"auth,auth-int\"";
|
"qop=\"auth,auth-int\"";
|
||||||
final AuthChallenge authChallenge = parse(challenge);
|
final AuthChallenge authChallenge = parse(challenge);
|
||||||
final HttpRequest request = new BasicHttpEntityEnclosingRequest("Post", "/");
|
|
||||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
|
||||||
final DigestScheme authscheme = new DigestScheme();
|
final DigestScheme authscheme = new DigestScheme();
|
||||||
final HttpContext context = new BasicHttpContext();
|
authscheme.processChallenge(authChallenge, null);
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||||
|
|
||||||
Assert.assertEquals("Post:/:d41d8cd98f00b204e9800998ecf8427e", authscheme.getA2());
|
Assert.assertEquals("Post:/:d41d8cd98f00b204e9800998ecf8427e", authscheme.getA2());
|
||||||
|
|
||||||
@ -578,16 +637,21 @@ public void testDigestAuthenticationQopAuthIntNullEntity() throws Exception {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDigestAuthenticationQopAuthOrAuthIntNonRepeatableEntity() throws Exception {
|
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\", " +
|
final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
|
||||||
"qop=\"auth,auth-int\"";
|
"qop=\"auth,auth-int\"";
|
||||||
final AuthChallenge authChallenge = parse(challenge);
|
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 DigestScheme authscheme = new DigestScheme();
|
||||||
final HttpContext context = new BasicHttpContext();
|
authscheme.processChallenge(authChallenge, null);
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
final Header authResponse = authscheme.authenticate(cred, request, context);
|
final String authResponse = authscheme.generateAuthResponse(host, request, null);
|
||||||
|
|
||||||
Assert.assertEquals("Post:/", authscheme.getA2());
|
Assert.assertEquals("Post:/", authscheme.getA2());
|
||||||
|
|
||||||
@ -601,32 +665,43 @@ public void testDigestAuthenticationQopAuthOrAuthIntNonRepeatableEntity() throws
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParameterCaseSensitivity() throws Exception {
|
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=\"-\", " +
|
final String challenge = "Digest Realm=\"-\", " +
|
||||||
"nonce=\"YjYuNGYyYmJhMzUuY2I5ZDhlZDE5M2ZlZDM 1Mjk3NGJkNTIyYjgyNTcwMjQ=\", " +
|
"nonce=\"YjYuNGYyYmJhMzUuY2I5ZDhlZDE5M2ZlZDM 1Mjk3NGJkNTIyYjgyNTcwMjQ=\", " +
|
||||||
"opaque=\"98700A3D9CE17065E2246B41035C6609\", qop=\"auth\"";
|
"opaque=\"98700A3D9CE17065E2246B41035C6609\", qop=\"auth\"";
|
||||||
final AuthChallenge authChallenge = parse(challenge);
|
final AuthChallenge authChallenge = parse(challenge);
|
||||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
|
||||||
final Credentials cred = new UsernamePasswordCredentials("username","password");
|
|
||||||
final DigestScheme authscheme = new DigestScheme();
|
final DigestScheme authscheme = new DigestScheme();
|
||||||
final HttpContext context = new BasicHttpContext();
|
authscheme.processChallenge(authChallenge, null);
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
|
||||||
Assert.assertEquals("-", authscheme.getRealm());
|
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)
|
@Test(expected=AuthenticationException.class)
|
||||||
public void testDigestAuthenticationQopIntOnlyNonRepeatableEntity() throws Exception {
|
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\", " +
|
final String challenge = "Digest realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
|
||||||
"qop=\"auth-int\"";
|
"qop=\"auth-int\"";
|
||||||
final AuthChallenge authChallenge = parse(challenge);
|
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 DigestScheme authscheme = new DigestScheme();
|
||||||
final HttpContext context = new BasicHttpContext();
|
authscheme.processChallenge(authChallenge, null);
|
||||||
authscheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
|
||||||
authscheme.authenticate(cred, request, context);
|
Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
|
||||||
|
authscheme.generateAuthResponse(host, request, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -635,7 +710,7 @@ public void testSerialization() throws Exception {
|
|||||||
"qop=\"auth,auth-int\"";
|
"qop=\"auth,auth-int\"";
|
||||||
final AuthChallenge authChallenge = parse(challenge);
|
final AuthChallenge authChallenge = parse(challenge);
|
||||||
final DigestScheme digestScheme = new DigestScheme();
|
final DigestScheme digestScheme = new DigestScheme();
|
||||||
digestScheme.processChallenge(ChallengeType.TARGET, authChallenge);
|
digestScheme.processChallenge(authChallenge, null);
|
||||||
|
|
||||||
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
final ObjectOutputStream out = new ObjectOutputStream(buffer);
|
final ObjectOutputStream out = new ObjectOutputStream(buffer);
|
||||||
@ -645,9 +720,9 @@ public void testSerialization() throws Exception {
|
|||||||
final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(raw));
|
final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(raw));
|
||||||
final DigestScheme authScheme = (DigestScheme) in.readObject();
|
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.getRealm(), authScheme.getRealm());
|
||||||
Assert.assertEquals(digestScheme.isComplete(), authScheme.isComplete());
|
Assert.assertEquals(digestScheme.isChallengeComplete(), authScheme.isChallengeComplete());
|
||||||
Assert.assertEquals(digestScheme.getA1(), authScheme.getA1());
|
Assert.assertEquals(digestScheme.getA1(), authScheme.getA1());
|
||||||
Assert.assertEquals(digestScheme.getA2(), authScheme.getA2());
|
Assert.assertEquals(digestScheme.getA2(), authScheme.getA2());
|
||||||
Assert.assertEquals(digestScheme.getCnonce(), authScheme.getCnonce());
|
Assert.assertEquals(digestScheme.getCnonce(), authScheme.getCnonce());
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.HttpStatus;
|
import org.apache.http.HttpStatus;
|
||||||
import org.apache.http.HttpVersion;
|
import org.apache.http.HttpVersion;
|
||||||
import org.apache.http.auth.AuthOption;
|
|
||||||
import org.apache.http.auth.AuthProtocolState;
|
import org.apache.http.auth.AuthProtocolState;
|
||||||
import org.apache.http.auth.AuthScheme;
|
import org.apache.http.auth.AuthScheme;
|
||||||
import org.apache.http.auth.AuthSchemeProvider;
|
import org.apache.http.auth.AuthSchemeProvider;
|
||||||
@ -44,11 +43,12 @@
|
|||||||
import org.apache.http.auth.AuthenticationException;
|
import org.apache.http.auth.AuthenticationException;
|
||||||
import org.apache.http.auth.ChallengeType;
|
import org.apache.http.auth.ChallengeType;
|
||||||
import org.apache.http.auth.Credentials;
|
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.AuthCache;
|
||||||
import org.apache.http.client.protocol.HttpClientContext;
|
import org.apache.http.client.protocol.HttpClientContext;
|
||||||
import org.apache.http.config.Lookup;
|
import org.apache.http.config.Lookup;
|
||||||
import org.apache.http.config.RegistryBuilder;
|
import org.apache.http.config.RegistryBuilder;
|
||||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
|
||||||
import org.apache.http.impl.client.DefaultAuthenticationStrategy;
|
import org.apache.http.impl.client.DefaultAuthenticationStrategy;
|
||||||
import org.apache.http.message.BasicHeader;
|
import org.apache.http.message.BasicHeader;
|
||||||
import org.apache.http.message.BasicHttpRequest;
|
import org.apache.http.message.BasicHttpRequest;
|
||||||
@ -68,8 +68,7 @@ public class TestHttpAuthenticator {
|
|||||||
private AuthScheme authScheme;
|
private AuthScheme authScheme;
|
||||||
private HttpContext context;
|
private HttpContext context;
|
||||||
private HttpHost defaultHost;
|
private HttpHost defaultHost;
|
||||||
private Credentials credentials;
|
private CredentialsProvider credentialsProvider;
|
||||||
private BasicCredentialsProvider credentialsProvider;
|
|
||||||
private Lookup<AuthSchemeProvider> authSchemeRegistry;
|
private Lookup<AuthSchemeProvider> authSchemeRegistry;
|
||||||
private AuthCache authCache;
|
private AuthCache authCache;
|
||||||
private HttpAuthenticator httpAuthenticator;
|
private HttpAuthenticator httpAuthenticator;
|
||||||
@ -78,14 +77,12 @@ public class TestHttpAuthenticator {
|
|||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
this.authState = new AuthState();
|
this.authState = new AuthState();
|
||||||
this.authScheme = Mockito.mock(AuthScheme.class);
|
this.authScheme = Mockito.mock(AuthScheme.class);
|
||||||
Mockito.when(this.authScheme.getSchemeName()).thenReturn("Basic");
|
Mockito.when(this.authScheme.getName()).thenReturn("Basic");
|
||||||
Mockito.when(this.authScheme.isComplete()).thenReturn(Boolean.TRUE);
|
Mockito.when(this.authScheme.isChallengeComplete()).thenReturn(Boolean.TRUE);
|
||||||
this.context = new BasicHttpContext();
|
this.context = new BasicHttpContext();
|
||||||
this.defaultHost = new HttpHost("localhost", 80);
|
this.defaultHost = new HttpHost("localhost", 80);
|
||||||
this.context.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, this.defaultHost);
|
this.context.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, this.defaultHost);
|
||||||
this.credentials = Mockito.mock(Credentials.class);
|
this.credentialsProvider = Mockito.mock(CredentialsProvider.class);
|
||||||
this.credentialsProvider = new BasicCredentialsProvider();
|
|
||||||
this.credentialsProvider.setCredentials(AuthScope.ANY, this.credentials);
|
|
||||||
this.context.setAttribute(HttpClientContext.CREDS_PROVIDER, this.credentialsProvider);
|
this.context.setAttribute(HttpClientContext.CREDS_PROVIDER, this.credentialsProvider);
|
||||||
this.authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create()
|
this.authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create()
|
||||||
.register("basic", new BasicSchemeFactory())
|
.register("basic", new BasicSchemeFactory())
|
||||||
@ -111,7 +108,7 @@ public void testAuthenticationRequestedAfterSuccess() throws Exception {
|
|||||||
final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
|
final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
|
||||||
response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=test");
|
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);
|
this.authState.setState(AuthProtocolState.SUCCESS);
|
||||||
|
|
||||||
Assert.assertTrue(this.httpAuthenticator.isChallenged(
|
Assert.assertTrue(this.httpAuthenticator.isChallenged(
|
||||||
@ -132,7 +129,7 @@ public void testAuthenticationNotRequestedUnchallenged() throws Exception {
|
|||||||
@Test
|
@Test
|
||||||
public void testAuthenticationNotRequestedSuccess1() throws Exception {
|
public void testAuthenticationNotRequestedSuccess1() throws Exception {
|
||||||
final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
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);
|
this.authState.setState(AuthProtocolState.CHALLENGED);
|
||||||
|
|
||||||
Assert.assertFalse(this.httpAuthenticator.isChallenged(
|
Assert.assertFalse(this.httpAuthenticator.isChallenged(
|
||||||
@ -145,7 +142,7 @@ public void testAuthenticationNotRequestedSuccess1() throws Exception {
|
|||||||
@Test
|
@Test
|
||||||
public void testAuthenticationNotRequestedSuccess2() throws Exception {
|
public void testAuthenticationNotRequestedSuccess2() throws Exception {
|
||||||
final HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
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);
|
this.authState.setState(AuthProtocolState.HANDSHAKE);
|
||||||
|
|
||||||
Assert.assertFalse(this.httpAuthenticator.isChallenged(
|
Assert.assertFalse(this.httpAuthenticator.isChallenged(
|
||||||
@ -163,20 +160,47 @@ public void testAuthentication() throws Exception {
|
|||||||
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "Digest realm=\"realm1\", nonce=\"1234\""));
|
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "Digest realm=\"realm1\", nonce=\"1234\""));
|
||||||
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "whatever realm=\"realm1\", stuff=\"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();
|
final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
|
||||||
|
|
||||||
Assert.assertTrue(this.httpAuthenticator.prepareAuthResponse(
|
Assert.assertTrue(this.httpAuthenticator.prepareAuthResponse(
|
||||||
host, ChallengeType.TARGET, response, authStrategy, this.authState, this.context));
|
host, ChallengeType.TARGET, response, authStrategy, this.authState, this.context));
|
||||||
Assert.assertEquals(AuthProtocolState.CHALLENGED, this.authState.getState());
|
Assert.assertEquals(AuthProtocolState.CHALLENGED, this.authState.getState());
|
||||||
|
|
||||||
final Queue<AuthOption> options = this.authState.getAuthOptions();
|
final Queue<AuthScheme> options = this.authState.getAuthOptions();
|
||||||
Assert.assertNotNull(options);
|
Assert.assertNotNull(options);
|
||||||
final AuthOption option1 = options.poll();
|
final AuthScheme authScheme1 = options.poll();
|
||||||
Assert.assertNotNull(option1);
|
Assert.assertNotNull(authScheme1);
|
||||||
Assert.assertEquals("digest", option1.getAuthScheme().getSchemeName());
|
Assert.assertEquals("digest", authScheme1.getName());
|
||||||
final AuthOption option2 = options.poll();
|
final AuthScheme authScheme2 = options.poll();
|
||||||
Assert.assertNotNull(option2);
|
Assert.assertNotNull(authScheme2);
|
||||||
Assert.assertEquals("basic", option2.getAuthScheme().getSchemeName());
|
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());
|
Assert.assertNull(options.poll());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,8 +235,6 @@ public void testAuthenticationNoCredentials() throws Exception {
|
|||||||
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"test\""));
|
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"test\""));
|
||||||
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "Digest realm=\"realm1\", nonce=\"1234\""));
|
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "Digest realm=\"realm1\", nonce=\"1234\""));
|
||||||
|
|
||||||
this.credentialsProvider.clear();
|
|
||||||
|
|
||||||
final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
|
final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
|
||||||
|
|
||||||
Assert.assertFalse(this.httpAuthenticator.prepareAuthResponse(
|
Assert.assertFalse(this.httpAuthenticator.prepareAuthResponse(
|
||||||
@ -227,7 +249,7 @@ public void testAuthenticationFailed() throws Exception {
|
|||||||
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "Digest realm=\"realm1\", nonce=\"1234\""));
|
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "Digest realm=\"realm1\", nonce=\"1234\""));
|
||||||
|
|
||||||
this.authState.setState(AuthProtocolState.CHALLENGED);
|
this.authState.setState(AuthProtocolState.CHALLENGED);
|
||||||
this.authState.update(this.authScheme, this.credentials);
|
this.authState.update(this.authScheme);
|
||||||
|
|
||||||
final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
|
final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
|
||||||
|
|
||||||
@ -267,12 +289,11 @@ public void testAuthenticationFailure() throws Exception {
|
|||||||
final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
|
final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
|
||||||
|
|
||||||
this.authState.setState(AuthProtocolState.CHALLENGED);
|
this.authState.setState(AuthProtocolState.CHALLENGED);
|
||||||
this.authState.update(new BasicScheme(), this.credentials);
|
this.authState.update(new BasicScheme());
|
||||||
|
|
||||||
Assert.assertFalse(this.httpAuthenticator.prepareAuthResponse(
|
Assert.assertFalse(this.httpAuthenticator.prepareAuthResponse(
|
||||||
host, ChallengeType.TARGET, response, authStrategy, this.authState, this.context));
|
host, ChallengeType.TARGET, response, authStrategy, this.authState, this.context));
|
||||||
Assert.assertEquals(AuthProtocolState.FAILURE, this.authState.getState());
|
Assert.assertEquals(AuthProtocolState.FAILURE, this.authState.getState());
|
||||||
Assert.assertNull(this.authState.getCredentials());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -286,7 +307,7 @@ public void testAuthenticationHandshaking() throws Exception {
|
|||||||
final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
|
final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
|
||||||
|
|
||||||
this.authState.setState(AuthProtocolState.CHALLENGED);
|
this.authState.setState(AuthProtocolState.CHALLENGED);
|
||||||
this.authState.update(new DigestScheme(), this.credentials);
|
this.authState.update(new DigestScheme());
|
||||||
|
|
||||||
Assert.assertTrue(this.httpAuthenticator.prepareAuthResponse(
|
Assert.assertTrue(this.httpAuthenticator.prepareAuthResponse(
|
||||||
host, ChallengeType.TARGET, response, authStrategy, this.authState, this.context));
|
host, ChallengeType.TARGET, response, authStrategy, this.authState, this.context));
|
||||||
@ -301,20 +322,23 @@ public void testAuthenticationNoMatchingChallenge() throws Exception {
|
|||||||
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "Digest realm=\"realm1\", nonce=\"1234\""));
|
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "Digest realm=\"realm1\", nonce=\"1234\""));
|
||||||
response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "whatever realm=\"realm1\", stuff=\"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();
|
final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
|
||||||
|
|
||||||
this.authState.setState(AuthProtocolState.CHALLENGED);
|
this.authState.setState(AuthProtocolState.CHALLENGED);
|
||||||
this.authState.update(new BasicScheme(), this.credentials);
|
this.authState.update(new BasicScheme());
|
||||||
|
|
||||||
Assert.assertTrue(this.httpAuthenticator.prepareAuthResponse(
|
Assert.assertTrue(this.httpAuthenticator.prepareAuthResponse(
|
||||||
host, ChallengeType.TARGET, response, authStrategy, this.authState, this.context));
|
host, ChallengeType.TARGET, response, authStrategy, this.authState, this.context));
|
||||||
Assert.assertEquals(AuthProtocolState.CHALLENGED, this.authState.getState());
|
Assert.assertEquals(AuthProtocolState.CHALLENGED, this.authState.getState());
|
||||||
|
|
||||||
final Queue<AuthOption> options = this.authState.getAuthOptions();
|
final Queue<AuthScheme> options = this.authState.getAuthOptions();
|
||||||
Assert.assertNotNull(options);
|
Assert.assertNotNull(options);
|
||||||
final AuthOption option1 = options.poll();
|
final AuthScheme authScheme1 = options.poll();
|
||||||
Assert.assertNotNull(option1);
|
Assert.assertNotNull(authScheme1);
|
||||||
Assert.assertEquals("digest", option1.getAuthScheme().getSchemeName());
|
Assert.assertEquals("digest", authScheme1.getName());
|
||||||
Assert.assertNull(options.poll());
|
Assert.assertNull(options.poll());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,21 +357,20 @@ public void testAuthenticationException() throws Exception {
|
|||||||
|
|
||||||
Assert.assertEquals(AuthProtocolState.UNCHALLENGED, this.authState.getState());
|
Assert.assertEquals(AuthProtocolState.UNCHALLENGED, this.authState.getState());
|
||||||
Assert.assertNull(this.authState.getAuthScheme());
|
Assert.assertNull(this.authState.getAuthScheme());
|
||||||
Assert.assertNull(this.authState.getCredentials());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAuthFailureState() throws Exception {
|
public void testAuthFailureState() throws Exception {
|
||||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||||
this.authState.setState(AuthProtocolState.FAILURE);
|
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));
|
Assert.assertFalse(request.containsHeader(HttpHeaders.AUTHORIZATION));
|
||||||
|
|
||||||
Mockito.verify(this.authScheme, Mockito.never()).authenticate(
|
Mockito.verify(this.authScheme, Mockito.never()).generateAuthResponse(
|
||||||
Mockito.any(Credentials.class),
|
Mockito.eq(defaultHost),
|
||||||
Mockito.any(HttpRequest.class),
|
Mockito.any(HttpRequest.class),
|
||||||
Mockito.any(HttpContext.class));
|
Mockito.any(HttpContext.class));
|
||||||
}
|
}
|
||||||
@ -356,42 +379,37 @@ public void testAuthFailureState() throws Exception {
|
|||||||
public void testAuthChallengeStateNoOption() throws Exception {
|
public void testAuthChallengeStateNoOption() throws Exception {
|
||||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||||
this.authState.setState(AuthProtocolState.CHALLENGED);
|
this.authState.setState(AuthProtocolState.CHALLENGED);
|
||||||
this.authState.update(this.authScheme, this.credentials);
|
this.authState.update(this.authScheme);
|
||||||
|
|
||||||
Mockito.when(this.authScheme.authenticate(
|
Mockito.when(this.authScheme.generateAuthResponse(
|
||||||
Mockito.any(Credentials.class),
|
Mockito.eq(defaultHost),
|
||||||
Mockito.any(HttpRequest.class),
|
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));
|
Assert.assertTrue(request.containsHeader(HttpHeaders.AUTHORIZATION));
|
||||||
|
|
||||||
Mockito.verify(this.authScheme).authenticate(this.credentials, request, this.context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAuthChallengeStateOneOptions() throws Exception {
|
public void testAuthChallengeStateOneOptions() throws Exception {
|
||||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||||
this.authState.setState(AuthProtocolState.CHALLENGED);
|
this.authState.setState(AuthProtocolState.CHALLENGED);
|
||||||
final LinkedList<AuthOption> authOptions = new LinkedList<>();
|
final LinkedList<AuthScheme> authOptions = new LinkedList<>();
|
||||||
authOptions.add(new AuthOption(this.authScheme, this.credentials));
|
authOptions.add(this.authScheme);
|
||||||
this.authState.update(authOptions);
|
this.authState.update(authOptions);
|
||||||
|
|
||||||
Mockito.when(this.authScheme.authenticate(
|
Mockito.when(this.authScheme.generateAuthResponse(
|
||||||
Mockito.any(Credentials.class),
|
Mockito.eq(defaultHost),
|
||||||
Mockito.any(HttpRequest.class),
|
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.authScheme, this.authState.getAuthScheme());
|
||||||
Assert.assertSame(this.credentials, this.authState.getCredentials());
|
|
||||||
Assert.assertNull(this.authState.getAuthOptions());
|
Assert.assertNull(this.authState.getAuthOptions());
|
||||||
|
|
||||||
Assert.assertTrue(request.containsHeader(HttpHeaders.AUTHORIZATION));
|
Assert.assertTrue(request.containsHeader(HttpHeaders.AUTHORIZATION));
|
||||||
|
|
||||||
Mockito.verify(this.authScheme).authenticate(this.credentials, request, this.context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -399,74 +417,67 @@ public void testAuthChallengeStateMultipleOption() throws Exception {
|
|||||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||||
this.authState.setState(AuthProtocolState.CHALLENGED);
|
this.authState.setState(AuthProtocolState.CHALLENGED);
|
||||||
|
|
||||||
final LinkedList<AuthOption> authOptions = new LinkedList<>();
|
final LinkedList<AuthScheme> authOptions = new LinkedList<>();
|
||||||
final AuthScheme authScheme1 = Mockito.mock(AuthScheme.class);
|
final AuthScheme authScheme1 = Mockito.mock(AuthScheme.class);
|
||||||
Mockito.doThrow(new AuthenticationException()).when(authScheme1).authenticate(
|
Mockito.doThrow(new AuthenticationException()).when(authScheme1).generateAuthResponse(
|
||||||
Mockito.any(Credentials.class),
|
Mockito.eq(defaultHost),
|
||||||
Mockito.any(HttpRequest.class),
|
Mockito.any(HttpRequest.class),
|
||||||
Mockito.any(HttpContext.class));
|
Mockito.any(HttpContext.class));
|
||||||
final AuthScheme authScheme2 = Mockito.mock(AuthScheme.class);
|
final AuthScheme authScheme2 = Mockito.mock(AuthScheme.class);
|
||||||
Mockito.when(authScheme2.authenticate(
|
Mockito.when(authScheme2.generateAuthResponse(
|
||||||
Mockito.any(Credentials.class),
|
Mockito.eq(defaultHost),
|
||||||
Mockito.any(HttpRequest.class),
|
Mockito.any(HttpRequest.class),
|
||||||
Mockito.any(HttpContext.class))).thenReturn(new BasicHeader(HttpHeaders.AUTHORIZATION, "stuff"));
|
Mockito.any(HttpContext.class))).thenReturn("stuff");
|
||||||
authOptions.add(new AuthOption(authScheme1, this.credentials));
|
authOptions.add(authScheme1);
|
||||||
authOptions.add(new AuthOption(authScheme2, this.credentials));
|
authOptions.add(authScheme2);
|
||||||
this.authState.update(authOptions);
|
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(authScheme2, this.authState.getAuthScheme());
|
||||||
Assert.assertSame(this.credentials, this.authState.getCredentials());
|
|
||||||
Assert.assertNull(this.authState.getAuthOptions());
|
Assert.assertNull(this.authState.getAuthOptions());
|
||||||
|
|
||||||
Assert.assertTrue(request.containsHeader(HttpHeaders.AUTHORIZATION));
|
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
|
@Test
|
||||||
public void testAuthSuccess() throws Exception {
|
public void testAuthSuccess() throws Exception {
|
||||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||||
this.authState.setState(AuthProtocolState.SUCCESS);
|
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.isConnectionBased()).thenReturn(Boolean.FALSE);
|
||||||
Mockito.when(this.authScheme.authenticate(
|
Mockito.when(this.authScheme.generateAuthResponse(
|
||||||
Mockito.any(Credentials.class),
|
Mockito.eq(defaultHost),
|
||||||
Mockito.any(HttpRequest.class),
|
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.authScheme, this.authState.getAuthScheme());
|
||||||
Assert.assertSame(this.credentials, this.authState.getCredentials());
|
|
||||||
Assert.assertNull(this.authState.getAuthOptions());
|
Assert.assertNull(this.authState.getAuthOptions());
|
||||||
|
|
||||||
Assert.assertTrue(request.containsHeader(HttpHeaders.AUTHORIZATION));
|
Assert.assertTrue(request.containsHeader(HttpHeaders.AUTHORIZATION));
|
||||||
|
|
||||||
Mockito.verify(this.authScheme).authenticate(this.credentials, request, this.context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAuthSuccessConnectionBased() throws Exception {
|
public void testAuthSuccessConnectionBased() throws Exception {
|
||||||
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
final HttpRequest request = new BasicHttpRequest("GET", "/");
|
||||||
this.authState.setState(AuthProtocolState.SUCCESS);
|
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.isConnectionBased()).thenReturn(Boolean.TRUE);
|
||||||
Mockito.when(this.authScheme.authenticate(
|
Mockito.when(this.authScheme.generateAuthResponse(
|
||||||
Mockito.any(Credentials.class),
|
Mockito.eq(defaultHost),
|
||||||
Mockito.any(HttpRequest.class),
|
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));
|
Assert.assertFalse(request.containsHeader(HttpHeaders.AUTHORIZATION));
|
||||||
|
|
||||||
Mockito.verify(this.authScheme, Mockito.never()).authenticate(
|
Mockito.verify(this.authScheme, Mockito.never()).generateAuthResponse(
|
||||||
Mockito.any(Credentials.class),
|
Mockito.eq(defaultHost),
|
||||||
Mockito.any(HttpRequest.class),
|
Mockito.any(HttpRequest.class),
|
||||||
Mockito.any(HttpContext.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 void testPreemptiveAuthentication() throws Exception {
|
|||||||
|
|
||||||
final HttpHost target = start();
|
final HttpHost target = start();
|
||||||
|
|
||||||
|
final BasicScheme basicScheme = new BasicScheme();
|
||||||
|
basicScheme.initPreemptive(new UsernamePasswordCredentials("test", "test"));
|
||||||
final HttpClientContext context = HttpClientContext.create();
|
final HttpClientContext context = HttpClientContext.create();
|
||||||
final AuthCache authCache = new BasicAuthCache();
|
final AuthCache authCache = new BasicAuthCache();
|
||||||
authCache.put(target, new BasicScheme());
|
authCache.put(target, basicScheme);
|
||||||
context.setAuthCache(authCache);
|
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 HttpGet httpget = new HttpGet("/");
|
||||||
final HttpResponse response1 = this.httpclient.execute(target, httpget, context);
|
final HttpResponse response1 = this.httpclient.execute(target, httpget, context);
|
||||||
|
@ -153,7 +153,7 @@ public AuthScheme create(final HttpContext context) {
|
|||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSchemeName() {
|
public String getName() {
|
||||||
return "MyBasic";
|
return "MyBasic";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,6 @@
|
|||||||
import org.apache.http.auth.AuthScope;
|
import org.apache.http.auth.AuthScope;
|
||||||
import org.apache.http.auth.AuthState;
|
import org.apache.http.auth.AuthState;
|
||||||
import org.apache.http.auth.ChallengeType;
|
import org.apache.http.auth.ChallengeType;
|
||||||
import org.apache.http.auth.NTCredentials;
|
|
||||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||||
import org.apache.http.client.AuthenticationStrategy;
|
import org.apache.http.client.AuthenticationStrategy;
|
||||||
import org.apache.http.client.NonRepeatableRequestException;
|
import org.apache.http.client.NonRepeatableRequestException;
|
||||||
@ -442,7 +441,7 @@ public void testExecEntityEnclosingRequestRetryOnAuthChallenge() throws Exceptio
|
|||||||
|
|
||||||
final AuthState proxyAuthState = new AuthState();
|
final AuthState proxyAuthState = new AuthState();
|
||||||
proxyAuthState.setState(AuthProtocolState.SUCCESS);
|
proxyAuthState.setState(AuthProtocolState.SUCCESS);
|
||||||
proxyAuthState.update(new NTLMScheme(), new NTCredentials("user:pass"));
|
proxyAuthState.update(new NTLMScheme());
|
||||||
|
|
||||||
final HttpClientContext context = new HttpClientContext();
|
final HttpClientContext context = new HttpClientContext();
|
||||||
context.setAttribute(HttpClientContext.PROXY_AUTH_STATE, proxyAuthState);
|
context.setAttribute(HttpClientContext.PROXY_AUTH_STATE, proxyAuthState);
|
||||||
@ -475,7 +474,6 @@ public void testExecEntityEnclosingRequestRetryOnAuthChallenge() throws Exceptio
|
|||||||
Assert.assertNotNull(finalResponse);
|
Assert.assertNotNull(finalResponse);
|
||||||
Assert.assertEquals(200, finalResponse.getStatusLine().getStatusCode());
|
Assert.assertEquals(200, finalResponse.getStatusLine().getStatusCode());
|
||||||
Assert.assertNull(proxyAuthState.getAuthScheme());
|
Assert.assertNull(proxyAuthState.getAuthScheme());
|
||||||
Assert.assertNull(proxyAuthState.getCredentials());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = NonRepeatableRequestException.class)
|
@Test(expected = NonRepeatableRequestException.class)
|
||||||
|
@ -26,6 +26,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.http.impl.execchain;
|
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.Header;
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.HttpEntity;
|
||||||
import org.apache.http.HttpException;
|
import org.apache.http.HttpException;
|
||||||
@ -35,8 +39,6 @@
|
|||||||
import org.apache.http.ProtocolException;
|
import org.apache.http.ProtocolException;
|
||||||
import org.apache.http.auth.AuthProtocolState;
|
import org.apache.http.auth.AuthProtocolState;
|
||||||
import org.apache.http.auth.AuthState;
|
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.RedirectException;
|
||||||
import org.apache.http.client.RedirectStrategy;
|
import org.apache.http.client.RedirectStrategy;
|
||||||
import org.apache.http.client.config.RequestConfig;
|
import org.apache.http.client.config.RequestConfig;
|
||||||
@ -60,10 +62,6 @@
|
|||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@SuppressWarnings({"boxing","static-access"}) // test code
|
@SuppressWarnings({"boxing","static-access"}) // test code
|
||||||
public class TestRedirectExec {
|
public class TestRedirectExec {
|
||||||
|
|
||||||
@ -240,10 +238,10 @@ public void testCrossSiteRedirect() throws Exception {
|
|||||||
|
|
||||||
final AuthState targetAuthState = new AuthState();
|
final AuthState targetAuthState = new AuthState();
|
||||||
targetAuthState.setState(AuthProtocolState.SUCCESS);
|
targetAuthState.setState(AuthProtocolState.SUCCESS);
|
||||||
targetAuthState.update(new BasicScheme(), new UsernamePasswordCredentials("user:pass"));
|
targetAuthState.update(new BasicScheme());
|
||||||
final AuthState proxyAuthState = new AuthState();
|
final AuthState proxyAuthState = new AuthState();
|
||||||
proxyAuthState.setState(AuthProtocolState.SUCCESS);
|
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.TARGET_AUTH_STATE, targetAuthState);
|
||||||
context.setAttribute(HttpClientContext.PROXY_AUTH_STATE, proxyAuthState);
|
context.setAttribute(HttpClientContext.PROXY_AUTH_STATE, proxyAuthState);
|
||||||
|
|
||||||
|
@ -546,7 +546,7 @@ HttpRoutePlanner routePlanner = new HttpRoutePlanner() {
|
|||||||
HttpRequest request,
|
HttpRequest request,
|
||||||
HttpContext context) throws HttpException {
|
HttpContext context) throws HttpException {
|
||||||
return new HttpRoute(target, null, new HttpHost("someproxy", 8080),
|
return new HttpRoute(target, null, new HttpHost("someproxy", 8080),
|
||||||
"https".equalsIgnoreCase(target.getSchemeName()));
|
"https".equalsIgnoreCase(target.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user