Skip to content

Commit

Permalink
When preemptive auth is disabled HTTP Sampler does not automatically …
Browse files Browse the repository at this point in the history
…respond to Basic Auth challenge

Bugzilla Id: 64267
  • Loading branch information
FSchumacher committed May 9, 2020
1 parent dc3d0e3 commit 740a206
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
Expand Down Expand Up @@ -62,6 +63,7 @@
import org.apache.http.auth.AuthState;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.NTCredentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.AuthenticationStrategy;
import org.apache.http.client.CredentialsProvider;
Expand Down Expand Up @@ -205,6 +207,80 @@ public class HTTPHC4Impl extends HTTPHCAbstractImpl {

private static final InputStreamFactory BROTLI = BrotliInputStream::new;

private static final class ManagedCredentialsProvider implements CredentialsProvider {
private AuthManager authManager;
private Credentials proxyCredentials;
private AuthScope proxyAuthScope;

public ManagedCredentialsProvider(AuthManager authManager, AuthScope proxyAuthScope, Credentials proxyCredentials) {
this.authManager = authManager;
this.proxyAuthScope = proxyAuthScope;
this.proxyCredentials = proxyCredentials;
}

@Override
public void setCredentials(AuthScope authscope, Credentials credentials) {
log.debug("Store creds {} for {}", credentials, authscope);
}

@Override
public Credentials getCredentials(AuthScope authScope) {
log.info("Get creds for {}", authScope);
if (this.proxyAuthScope != null && authScope.equals(proxyAuthScope)) {
return proxyCredentials;
}
final Authorization authorization = getAuthorizationForAuthScope(authScope);
if (authorization == null) {
return null;
}
return new UsernamePasswordCredentials(authorization.getUser(), authorization.getPass());
}

/**
* Find the Authorization for the given AuthScope. We can't ask the AuthManager
* by the URL, as we didn't get the scheme or path of the URL. Therefore we do a
* best guess on the information we have
*
* @param authScope information which destination we want to get credentials for
* @return matching authorization information entry from the AuthManager
*/
private Authorization getAuthorizationForAuthScope(AuthScope authScope) {
if (authScope == null) {
return null;
}
for (JMeterProperty authProp : authManager.getAuthObjects()) {
Object authObject = authProp.getObjectValue();
if (authObject instanceof Authorization) {
Authorization auth = (Authorization) authObject;
if (!authScope.getRealm().equals(auth.getRealm())) {
continue;
}
try {
URL authUrl = new URL(auth.getURL());
if (authUrl.getHost().equals(authScope.getHost()) && getPort(authUrl) == authScope.getPort()) {
return auth;
}
} catch (MalformedURLException e) {
log.debug("Invalid URL {} in authManager", auth.getURL());
}
}
}
return null;
}

private int getPort(URL url) {
if (url.getPort() == -1) {
return url.getProtocol().equals("https") ? 443 : 80;
}
return url.getPort();
}

@Override
public void clear() {
log.debug("clear creds");
}
}

private static final class PreemptiveAuthRequestInterceptor implements HttpRequestInterceptor {
@Override
public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
Expand Down Expand Up @@ -1055,21 +1131,27 @@ private MutableTriple<CloseableHttpClient, AuthState, PoolingHttpClientConnectio
}

// Set up proxy details
AuthScope proxyAuthScope = null;
NTCredentials proxyCredentials = null;
if (key.hasProxy) {
HttpHost proxy = new HttpHost(key.proxyHost, key.proxyPort, key.proxyScheme);
builder.setProxy(proxy);

CredentialsProvider credsProvider = new BasicCredentialsProvider();
if (!key.proxyUser.isEmpty()) {
proxyAuthScope = new AuthScope(key.proxyHost, key.proxyPort);
proxyCredentials = new NTCredentials(key.proxyUser, key.proxyPass, LOCALHOST, PROXY_DOMAIN);
credsProvider.setCredentials(
new AuthScope(key.proxyHost, key.proxyPort),
new NTCredentials(key.proxyUser, key.proxyPass, LOCALHOST, PROXY_DOMAIN));
proxyAuthScope,
proxyCredentials);
}
builder.setDefaultCredentialsProvider(credsProvider);
}
builder.disableContentCompression().addInterceptorLast(RESPONSE_CONTENT_ENCODING);
if(BASIC_AUTH_PREEMPTIVE) {
builder.addInterceptorFirst(PREEMPTIVE_AUTH_INTERCEPTOR);
} else {
builder.setDefaultCredentialsProvider(new ManagedCredentialsProvider(getAuthManager(), proxyAuthScope, proxyCredentials));
}
httpClient = builder.build();
if (log.isDebugEnabled()) {
Expand Down
1 change: 1 addition & 0 deletions xdocs/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ Counter Config, XPath2 Extractor, Function Helper Dialog, Search popup, JMS Elem
<h3>HTTP Samplers and Test Script Recorder</h3>
<ul>
<li><bug>64400</bug>Make sorting recorded samples into transaction controllers more predictable</li>
<li><bug>64267</bug>When preemptive auth is disabled HTTP Sampler does not automatically respond to Basic Auth challenge</li>
</ul>

<h3>Other Samplers</h3>
Expand Down

0 comments on commit 740a206

Please sign in to comment.