This is an automated email from the ASF dual-hosted git repository.

fschumacher pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jmeter.git


The following commit(s) were added to refs/heads/master by this push:
     new 740a206  When preemptive auth is disabled HTTP Sampler does not 
automatically respond to Basic Auth challenge
740a206 is described below

commit 740a2066b01f5a0ad6633bb9b617022918d37d65
Author: Felix Schumacher <felix.schumac...@internetallee.de>
AuthorDate: Sat May 9 11:55:31 2020 +0200

    When preemptive auth is disabled HTTP Sampler does not automatically 
respond to Basic Auth challenge
    
    Bugzilla Id: 64267
---
 .../jmeter/protocol/http/sampler/HTTPHC4Impl.java  | 86 +++++++++++++++++++++-
 xdocs/changes.xml                                  |  1 +
 2 files changed, 85 insertions(+), 2 deletions(-)

diff --git 
a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
 
b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
index 8d4dd85..4824ed6 100644
--- 
a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
+++ 
b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
@@ -24,6 +24,7 @@ import java.io.OutputStream;
 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;
@@ -62,6 +63,7 @@ import org.apache.http.auth.AuthScope;
 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;
@@ -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 {
@@ -1055,21 +1131,27 @@ public class HTTPHC4Impl extends HTTPHCAbstractImpl {
             }
 
             // 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()) {
diff --git a/xdocs/changes.xml b/xdocs/changes.xml
index b5428ca..24d5281 100644
--- a/xdocs/changes.xml
+++ b/xdocs/changes.xml
@@ -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>

Reply via email to