Skip to content

Commit 740a206

Browse files
committed
When preemptive auth is disabled HTTP Sampler does not automatically respond to Basic Auth challenge
Bugzilla Id: 64267
1 parent dc3d0e3 commit 740a206

File tree

2 files changed

+85
-2
lines changed

2 files changed

+85
-2
lines changed

src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java

+84-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.io.UnsupportedEncodingException;
2525
import java.net.InetAddress;
2626
import java.net.InetSocketAddress;
27+
import java.net.MalformedURLException;
2728
import java.net.URI;
2829
import java.net.URISyntaxException;
2930
import java.net.URL;
@@ -62,6 +63,7 @@
6263
import org.apache.http.auth.AuthState;
6364
import org.apache.http.auth.Credentials;
6465
import org.apache.http.auth.NTCredentials;
66+
import org.apache.http.auth.UsernamePasswordCredentials;
6567
import org.apache.http.client.AuthCache;
6668
import org.apache.http.client.AuthenticationStrategy;
6769
import org.apache.http.client.CredentialsProvider;
@@ -205,6 +207,80 @@ public class HTTPHC4Impl extends HTTPHCAbstractImpl {
205207

206208
private static final InputStreamFactory BROTLI = BrotliInputStream::new;
207209

210+
private static final class ManagedCredentialsProvider implements CredentialsProvider {
211+
private AuthManager authManager;
212+
private Credentials proxyCredentials;
213+
private AuthScope proxyAuthScope;
214+
215+
public ManagedCredentialsProvider(AuthManager authManager, AuthScope proxyAuthScope, Credentials proxyCredentials) {
216+
this.authManager = authManager;
217+
this.proxyAuthScope = proxyAuthScope;
218+
this.proxyCredentials = proxyCredentials;
219+
}
220+
221+
@Override
222+
public void setCredentials(AuthScope authscope, Credentials credentials) {
223+
log.debug("Store creds {} for {}", credentials, authscope);
224+
}
225+
226+
@Override
227+
public Credentials getCredentials(AuthScope authScope) {
228+
log.info("Get creds for {}", authScope);
229+
if (this.proxyAuthScope != null && authScope.equals(proxyAuthScope)) {
230+
return proxyCredentials;
231+
}
232+
final Authorization authorization = getAuthorizationForAuthScope(authScope);
233+
if (authorization == null) {
234+
return null;
235+
}
236+
return new UsernamePasswordCredentials(authorization.getUser(), authorization.getPass());
237+
}
238+
239+
/**
240+
* Find the Authorization for the given AuthScope. We can't ask the AuthManager
241+
* by the URL, as we didn't get the scheme or path of the URL. Therefore we do a
242+
* best guess on the information we have
243+
*
244+
* @param authScope information which destination we want to get credentials for
245+
* @return matching authorization information entry from the AuthManager
246+
*/
247+
private Authorization getAuthorizationForAuthScope(AuthScope authScope) {
248+
if (authScope == null) {
249+
return null;
250+
}
251+
for (JMeterProperty authProp : authManager.getAuthObjects()) {
252+
Object authObject = authProp.getObjectValue();
253+
if (authObject instanceof Authorization) {
254+
Authorization auth = (Authorization) authObject;
255+
if (!authScope.getRealm().equals(auth.getRealm())) {
256+
continue;
257+
}
258+
try {
259+
URL authUrl = new URL(auth.getURL());
260+
if (authUrl.getHost().equals(authScope.getHost()) && getPort(authUrl) == authScope.getPort()) {
261+
return auth;
262+
}
263+
} catch (MalformedURLException e) {
264+
log.debug("Invalid URL {} in authManager", auth.getURL());
265+
}
266+
}
267+
}
268+
return null;
269+
}
270+
271+
private int getPort(URL url) {
272+
if (url.getPort() == -1) {
273+
return url.getProtocol().equals("https") ? 443 : 80;
274+
}
275+
return url.getPort();
276+
}
277+
278+
@Override
279+
public void clear() {
280+
log.debug("clear creds");
281+
}
282+
}
283+
208284
private static final class PreemptiveAuthRequestInterceptor implements HttpRequestInterceptor {
209285
@Override
210286
public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
@@ -1055,21 +1131,27 @@ private MutableTriple<CloseableHttpClient, AuthState, PoolingHttpClientConnectio
10551131
}
10561132

10571133
// Set up proxy details
1134+
AuthScope proxyAuthScope = null;
1135+
NTCredentials proxyCredentials = null;
10581136
if (key.hasProxy) {
10591137
HttpHost proxy = new HttpHost(key.proxyHost, key.proxyPort, key.proxyScheme);
10601138
builder.setProxy(proxy);
10611139

10621140
CredentialsProvider credsProvider = new BasicCredentialsProvider();
10631141
if (!key.proxyUser.isEmpty()) {
1142+
proxyAuthScope = new AuthScope(key.proxyHost, key.proxyPort);
1143+
proxyCredentials = new NTCredentials(key.proxyUser, key.proxyPass, LOCALHOST, PROXY_DOMAIN);
10641144
credsProvider.setCredentials(
1065-
new AuthScope(key.proxyHost, key.proxyPort),
1066-
new NTCredentials(key.proxyUser, key.proxyPass, LOCALHOST, PROXY_DOMAIN));
1145+
proxyAuthScope,
1146+
proxyCredentials);
10671147
}
10681148
builder.setDefaultCredentialsProvider(credsProvider);
10691149
}
10701150
builder.disableContentCompression().addInterceptorLast(RESPONSE_CONTENT_ENCODING);
10711151
if(BASIC_AUTH_PREEMPTIVE) {
10721152
builder.addInterceptorFirst(PREEMPTIVE_AUTH_INTERCEPTOR);
1153+
} else {
1154+
builder.setDefaultCredentialsProvider(new ManagedCredentialsProvider(getAuthManager(), proxyAuthScope, proxyCredentials));
10731155
}
10741156
httpClient = builder.build();
10751157
if (log.isDebugEnabled()) {

xdocs/changes.xml

+1
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ Counter Config, XPath2 Extractor, Function Helper Dialog, Search popup, JMS Elem
237237
<h3>HTTP Samplers and Test Script Recorder</h3>
238238
<ul>
239239
<li><bug>64400</bug>Make sorting recorded samples into transaction controllers more predictable</li>
240+
<li><bug>64267</bug>When preemptive auth is disabled HTTP Sampler does not automatically respond to Basic Auth challenge</li>
240241
</ul>
241242

242243
<h3>Other Samplers</h3>

0 commit comments

Comments
 (0)