You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ab...@apache.org on 2017/02/09 20:09:57 UTC

[40/50] lucene-solr:jira/solr-9858: SOLR-9997: Enable configuring SolrHttpClientBuilder via java system property.

SOLR-9997: Enable configuring SolrHttpClientBuilder via java system property.


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/e1a57764
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/e1a57764
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/e1a57764

Branch: refs/heads/jira/solr-9858
Commit: e1a577645756addc8ed060024e4af7ccd15c2321
Parents: 37b75be
Author: markrmiller <ma...@apache.org>
Authored: Tue Feb 7 13:15:51 2017 -0500
Committer: markrmiller <ma...@apache.org>
Committed: Tue Feb 7 13:15:51 2017 -0500

----------------------------------------------------------------------
 solr/CHANGES.txt                                |   1 +
 solr/bin/solr                                   |  31 ++++-
 solr/bin/solr.cmd                               |  37 +++++-
 solr/bin/solr.in.cmd                            |   4 +-
 solr/bin/solr.in.sh                             |   4 +-
 .../apache/solr/security/HadoopAuthPlugin.java  |  37 ++++++
 .../src/java/org/apache/solr/util/SolrCLI.java  |  39 ------
 .../solr/client/solrj/impl/HttpClientUtil.java  |  37 ++++--
 .../solrj/impl/Krb5HttpClientBuilder.java       |   5 +-
 .../solr/client/solrj/impl/PreemptiveAuth.java  |  59 +++++++++
 ...PreemptiveBasicAuthClientBuilderFactory.java | 132 +++++++++++++++++++
 11 files changed, 330 insertions(+), 56 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index a93bb00..96b06a6 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -128,6 +128,7 @@ New Features
 
 * SOLR-10087: StreamHandler now supports registering custom streaming expressions from the blob store (Kevin Risden)
 
+* SOLR-9997: Enable configuring SolrHttpClientBuilder via java system property. (Hrishikesh Gadre via Mark Miller)
 
 Bug Fixes
 ----------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/bin/solr
----------------------------------------------------------------------
diff --git a/solr/bin/solr b/solr/bin/solr
index cf9765d..cd9db0f 100755
--- a/solr/bin/solr
+++ b/solr/bin/solr
@@ -232,12 +232,39 @@ else
 fi
 
 # Authentication options
+if [ -z "$SOLR_AUTH_TYPE" ] && [ -n "$SOLR_AUTHENTICATION_OPTS" ]; then
+  echo "WARNING: SOLR_AUTHENTICATION_OPTS environment variable configured without associated SOLR_AUTH_TYPE variable"
+  echo "         Please configure SOLR_AUTH_TYPE environment variable with the authentication type to be used."
+  echo "         Currently supported authentication types are [kerberos, basic]"
+fi
+
+if [ -n "$SOLR_AUTH_TYPE" ] && [ -n "$SOLR_AUTHENTICATION_CLIENT_BUILDER" ]; then
+  echo "WARNING: SOLR_AUTHENTICATION_CLIENT_BUILDER and SOLR_AUTH_TYPE environment variables are configured together."
+  echo "         Use SOLR_AUTH_TYPE environment variable to configure authentication type to be used. "
+  echo "         Currently supported authentication types are [kerberos, basic]"
+  echo "         The value of SOLR_AUTHENTICATION_CLIENT_BUILDER environment variable will be ignored"
+fi
+
+if [ -n "$SOLR_AUTH_TYPE" ]; then
+  case "$(echo $SOLR_AUTH_TYPE | awk '{print tolower($0)}')" in
+    basic)
+      SOLR_AUTHENTICATION_CLIENT_BUILDER="org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory"
+      ;;
+    kerberos)
+      SOLR_AUTHENTICATION_CLIENT_BUILDER="org.apache.solr.client.solrj.impl.Krb5HttpClientBuilder"
+      ;;
+    *)
+      echo "ERROR: Value specified for SOLR_AUTH_TYPE environment variable is invalid."
+      exit 1
+   esac
+fi
+
 if [ "$SOLR_AUTHENTICATION_CLIENT_CONFIGURER" != "" ]; then
   echo "WARNING: Found unsupported configuration variable SOLR_AUTHENTICATION_CLIENT_CONFIGURER"
-  echo "         Please start using SOLR_AUTHENTICATION_CLIENT_BUILDER instead"
+  echo "         Please start using SOLR_AUTH_TYPE instead"
 fi
 if [ "$SOLR_AUTHENTICATION_CLIENT_BUILDER" != "" ]; then
-  AUTHC_CLIENT_BUILDER_ARG="-Dsolr.authentication.httpclient.builder=$SOLR_AUTHENTICATION_CLIENT_BUILDER"
+  AUTHC_CLIENT_BUILDER_ARG="-Dsolr.httpclient.builder.factory=$SOLR_AUTHENTICATION_CLIENT_BUILDER"
 fi
 AUTHC_OPTS="$AUTHC_CLIENT_BUILDER_ARG $SOLR_AUTHENTICATION_OPTS"
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/bin/solr.cmd
----------------------------------------------------------------------
diff --git a/solr/bin/solr.cmd b/solr/bin/solr.cmd
index 6cd0096..29422f3 100644
--- a/solr/bin/solr.cmd
+++ b/solr/bin/solr.cmd
@@ -117,12 +117,43 @@ IF DEFINED SOLR_SSL_KEY_STORE (
 )
 
 REM Authentication options
+
+IF NOT DEFINED SOLR_AUTH_TYPE (
+  IF DEFINED SOLR_AUTHENTICATION_OPTS (
+    echo WARNING: SOLR_AUTHENTICATION_OPTS variable configured without associated SOLR_AUTH_TYPE variable
+    echo          Please configure SOLR_AUTH_TYPE variable with the authentication type to be used.
+    echo          Currently supported authentication types are [kerberos, basic]
+  )
+)
+
+IF DEFINED SOLR_AUTH_TYPE (
+  IF DEFINED SOLR_AUTHENTICATION_CLIENT_BUILDER (
+    echo WARNING: SOLR_AUTHENTICATION_CLIENT_BUILDER and SOLR_AUTH_TYPE variables are configured together
+    echo          Use SOLR_AUTH_TYPE variable to configure authentication type to be used
+    echo          Currently supported authentication types are [kerberos, basic]
+    echo          The value of SOLR_AUTHENTICATION_CLIENT_BUILDER configuration variable will be ignored
+  )
+)
+
+IF DEFINED SOLR_AUTH_TYPE (
+  IF /I "%SOLR_AUTH_TYPE%" == "basic" (
+    set SOLR_AUTHENTICATION_CLIENT_BUILDER="org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory"
+  ) ELSE (
+    IF /I "%SOLR_AUTH_TYPE%" == "kerberos" (
+      set SOLR_AUTHENTICATION_CLIENT_BUILDER="org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory"
+    ) ELSE (
+      echo ERROR: Value specified for SOLR_AUTH_TYPE configuration variable is invalid.
+      goto err
+    )
+  )
+)
+
 IF DEFINED SOLR_AUTHENTICATION_CLIENT_CONFIGURER (
   echo WARNING: Found unsupported configuration variable SOLR_AUTHENTICATION_CLIENT_CONFIGURER
-  echo          Please start using SOLR_AUTHENTICATION_CLIENT_BUILDER instead
+  echo          Please start using SOLR_AUTH_TYPE instead
 )
 IF DEFINED SOLR_AUTHENTICATION_CLIENT_BUILDER (
-  set AUTHC_CLIENT_BUILDER_ARG="-Dsolr.authentication.httpclient.builder=%SOLR_AUTHENTICATION_CLIENT_BUILDER%"
+  set AUTHC_CLIENT_BUILDER_ARG="-Dsolr.httpclient.builder.factory=%SOLR_AUTHENTICATION_CLIENT_BUILDER%"
 )
 set "AUTHC_OPTS=%AUTHC_CLIENT_BUILDER_ARG% %SOLR_AUTHENTICATION_OPTS%"
 
@@ -1154,7 +1185,7 @@ for /f "usebackq" %%i in (`dir /b "%SOLR_TIP%\bin" ^| findstr /i "^solr-.*\.port
           @echo.
           set has_info=1
           echo Found Solr process %%k running on port !SOME_SOLR_PORT!
-          "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^ 
+          "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" ^
             -Dlog4j.configuration="file:%DEFAULT_SERVER_DIR%\scripts\cloud-scripts\log4j.properties" ^
             -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^
             org.apache.solr.util.SolrCLI status -solr !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:!SOME_SOLR_PORT!/solr

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/bin/solr.in.cmd
----------------------------------------------------------------------
diff --git a/solr/bin/solr.in.cmd b/solr/bin/solr.in.cmd
index e565c02..279e03e 100644
--- a/solr/bin/solr.in.cmd
+++ b/solr/bin/solr.in.cmd
@@ -108,7 +108,9 @@ REM set SOLR_SSL_CLIENT_TRUST_STORE_PASSWORD=
 REM set SOLR_SSL_CLIENT_TRUST_STORE_TYPE=
 
 REM Settings for authentication
-REM set SOLR_AUTHENTICATION_CLIENT_BUILDER=
+REM Please configure only one of SOLR_AUTHENTICATION_CLIENT_BUILDER or SOLR_AUTH_TYPE parameters
+REM set SOLR_AUTHENTICATION_CLIENT_BUILDER=org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory
+REM set SOLR_AUTH_TYPE=basic
 REM set SOLR_AUTHENTICATION_OPTS="-Dbasicauth=solr:SolrRocks"
 
 REM Settings for ZK ACL

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/bin/solr.in.sh
----------------------------------------------------------------------
diff --git a/solr/bin/solr.in.sh b/solr/bin/solr.in.sh
index 5a9f807..878702f 100644
--- a/solr/bin/solr.in.sh
+++ b/solr/bin/solr.in.sh
@@ -120,7 +120,9 @@
 #SOLR_SSL_CLIENT_TRUST_STORE_TYPE=
 
 # Settings for authentication
-#SOLR_AUTHENTICATION_CLIENT_BUILDER=
+# Please configure only one of SOLR_AUTHENTICATION_CLIENT_BUILDER or SOLR_AUTH_TYPE parameters
+#SOLR_AUTHENTICATION_CLIENT_BUILDER="org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory"
+#SOLR_AUTH_TYPE="basic"
 #SOLR_AUTHENTICATION_OPTS="-Dbasicauth=solr:SolrRocks"
 
 # Settings for ZK ACL

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/core/src/java/org/apache/solr/security/HadoopAuthPlugin.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/security/HadoopAuthPlugin.java b/solr/core/src/java/org/apache/solr/security/HadoopAuthPlugin.java
index 1f0d5ad..fa59d38 100644
--- a/solr/core/src/java/org/apache/solr/security/HadoopAuthPlugin.java
+++ b/solr/core/src/java/org/apache/solr/security/HadoopAuthPlugin.java
@@ -34,6 +34,7 @@ import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponseWrapper;
 
@@ -112,6 +113,12 @@ public class HadoopAuthPlugin extends AuthenticationPlugin {
    */
   public static final String PROXY_USER_CONFIGS = "proxyUserConfigs";
 
+  /**
+   * This parameter is used to debug the authentication related issues during development.
+   * This should not be used in production.
+   */
+  private static final boolean TRACE_HTTP = Boolean.getBoolean("hadoopauth.tracehttp");
+
   private AuthenticationFilter authFilter;
   protected final CoreContainer coreContainer;
 
@@ -204,6 +211,23 @@ public class HadoopAuthPlugin extends AuthenticationPlugin {
       throws Exception {
     final HttpServletResponse frsp = (HttpServletResponse)response;
 
+    if (TRACE_HTTP) {
+      HttpServletRequest req = (HttpServletRequest) request;
+      log.info("----------HTTP Request---------");
+      log.info("{} : {}", req.getMethod(), req.getRequestURI());
+      log.info("Query : {}", req.getQueryString());
+      log.info("Headers :");
+      Enumeration<String> headers = req.getHeaderNames();
+      while (headers.hasMoreElements()) {
+        String name = headers.nextElement();
+        Enumeration<String> hvals = req.getHeaders(name);
+        while (hvals.hasMoreElements()) {
+          log.info("{} : {}", name, hvals.nextElement());
+        }
+      }
+      log.info("-------------------------------");
+    }
+
     // Workaround until HADOOP-13346 is fixed.
     HttpServletResponse rspCloseShield = new HttpServletResponseWrapper(frsp) {
       @SuppressForbidden(reason = "Hadoop DelegationTokenAuthenticationFilter uses response writer, this" +
@@ -219,6 +243,19 @@ public class HadoopAuthPlugin extends AuthenticationPlugin {
     };
     authFilter.doFilter(request, rspCloseShield, filterChain);
 
+    if (TRACE_HTTP) {
+      log.info("----------HTTP Response---------");
+      log.info("Status : {}", frsp.getStatus());
+      log.info("Headers :");
+      for (String name : frsp.getHeaderNames()) {
+        for (String value : frsp.getHeaders(name)) {
+          log.info("{} : {}", name, value);
+        }
+      }
+      log.info("-------------------------------");
+    }
+
+
     if (authFilter instanceof HadoopAuthFilter) { // delegation token mgmt.
       String requestContinuesAttr = (String)request.getAttribute(REQUEST_CONTINUES_ATTR);
       if (requestContinuesAttr == null) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/core/src/java/org/apache/solr/util/SolrCLI.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/SolrCLI.java b/solr/core/src/java/org/apache/solr/util/SolrCLI.java
index bb2d554..4f6cf8d 100644
--- a/solr/core/src/java/org/apache/solr/util/SolrCLI.java
+++ b/solr/core/src/java/org/apache/solr/util/SolrCLI.java
@@ -60,7 +60,6 @@ import org.apache.commons.cli.Option;
 import org.apache.commons.cli.OptionBuilder;
 import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
-import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.exec.DefaultExecuteResultHandler;
 import org.apache.commons.exec.DefaultExecutor;
 import org.apache.commons.exec.Executor;
@@ -80,7 +79,6 @@ import org.apache.http.client.methods.HttpHead;
 import org.apache.http.client.utils.URIBuilder;
 import org.apache.http.conn.ConnectTimeoutException;
 import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.message.BasicHeader;
 import org.apache.http.util.EntityUtils;
 import org.apache.lucene.util.Version;
 import org.apache.solr.client.solrj.SolrClient;
@@ -90,7 +88,6 @@ import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.impl.HttpSolrClient.Builder;
-import org.apache.solr.client.solrj.impl.SolrHttpClientBuilder;
 import org.apache.solr.client.solrj.impl.ZkClientClusterStateProvider;
 import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest;
 import org.apache.solr.client.solrj.response.QueryResponse;
@@ -106,7 +103,6 @@ import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.util.ContentStreamBase;
 import org.apache.solr.common.util.NamedList;
-import org.apache.solr.common.util.StrUtils;
 import org.noggit.CharArr;
 import org.noggit.JSONParser;
 import org.noggit.JSONWriter;
@@ -153,7 +149,6 @@ public class SolrCLI {
 
       int toolExitStatus = 0;
       try {
-        setBasicAuth();
         runImpl(cli);
       } catch (Exception exc) {
         // since this is a CLI, spare the user the stacktrace
@@ -261,20 +256,6 @@ public class SolrCLI {
   }
 
   public static CommandLine parseCmdLine(String[] args, Option[] toolOptions) throws Exception {
-
-    String builderClassName = System.getProperty("solr.authentication.httpclient.builder");
-    if (builderClassName!=null) {
-      try {
-        Class c = Class.forName(builderClassName);
-        SolrHttpClientBuilder builder = (SolrHttpClientBuilder)c.newInstance();
-        HttpClientUtil.setHttpClientBuilder(builder);
-        log.info("Set SolrHttpClientBuilder from: "+builderClassName);
-      } catch (Exception ex) {
-        log.error(ex.getMessage());
-        throw new RuntimeException("Error during loading of builder '"+builderClassName+"'.", ex);
-      }
-    }
-
     // the parser doesn't like -D props
     List<String> toolArgList = new ArrayList<String>();
     List<String> dashDList = new ArrayList<String>();
@@ -532,25 +513,6 @@ public class SolrCLI {
   }
 
   /**
-   * Inspects system property basicauth and enables authentication for HttpClient
-   * @throws Exception if the basicauth SysProp has wrong format
-   */
-  protected static void setBasicAuth() throws Exception {
-    String basicauth = System.getProperty("basicauth", null);
-    if (basicauth != null) {
-      List<String> ss = StrUtils.splitSmart(basicauth, ':');
-      if (ss.size() != 2)
-        throw new Exception("Please provide 'basicauth' in the 'user:password' format");
-
-      HttpClientUtil.addRequestInterceptor((httpRequest, httpContext) -> {
-        String pair = ss.get(0) + ":" + ss.get(1);
-        byte[] encodedBytes = Base64.encodeBase64(pair.getBytes(UTF_8));
-        httpRequest.addHeader(new BasicHeader("Authorization", "Basic " + new String(encodedBytes, UTF_8)));
-      });
-    }
-  }
-  
-  /**
    * Determine if a request to Solr failed due to a communication error,
    * which is generally retry-able. 
    */
@@ -3341,7 +3303,6 @@ public class SolrCLI {
 
       int toolExitStatus = 0;
       try {
-        setBasicAuth();
         toolExitStatus = runAssert(cli);
       } catch (Exception exc) {
         // since this is a CLI, spare the user the stacktrace

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java
index decd5e8..7ee90e1 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java
@@ -22,6 +22,7 @@ import java.lang.invoke.MethodHandles;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 import java.util.zip.GZIPInputStream;
@@ -111,28 +112,46 @@ public class HttpClientUtil {
   // cannot be established within x ms. with a
   // java.net.SocketTimeoutException: Connection timed out
   public static final String PROP_CONNECTION_TIMEOUT = "connTimeout";
-  
+
+  /**
+   * A Java system property to select the {@linkplain HttpClientBuilderFactory} used for
+   * configuring the {@linkplain HttpClientBuilder} instance by default.
+   */
+  public static final String SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY = "solr.httpclient.builder.factory";
+
   static final DefaultHttpRequestRetryHandler NO_RETRY = new DefaultHttpRequestRetryHandler(
       0, false);
 
   private static volatile SolrHttpClientBuilder httpClientBuilder;
-  
+
   private static SolrHttpClientContextBuilder httpClientRequestContextBuilder = new SolrHttpClientContextBuilder();
-  
+
+  private static volatile SchemaRegistryProvider schemaRegistryProvider;
+  private static volatile String cookiePolicy;
+  private static final List<HttpRequestInterceptor> interceptors = Collections.synchronizedList(new ArrayList<HttpRequestInterceptor>());
+
+
   static {
     resetHttpClientBuilder();
+
+    // Configure the HttpClientBuilder if user has specified the factory type.
+    String factoryClassName = System.getProperty(SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY);
+    if (factoryClassName != null) {
+      logger.debug ("Using " + factoryClassName);
+      try {
+        HttpClientBuilderFactory factory = (HttpClientBuilderFactory)Class.forName(factoryClassName).newInstance();
+        httpClientBuilder = factory.getHttpClientBuilder(Optional.of(SolrHttpClientBuilder.create()));
+      } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
+        throw new RuntimeException("Unable to instantiate Solr HttpClientBuilderFactory", e);
+      }
+    }
   }
 
   public static abstract class SchemaRegistryProvider {
     /** Must be non-null */
     public abstract Registry<ConnectionSocketFactory> getSchemaRegistry();
   }
-  
-  private static volatile SchemaRegistryProvider schemaRegistryProvider;
-  private static volatile String cookiePolicy;
 
-  private static final List<HttpRequestInterceptor> interceptors = Collections.synchronizedList(new ArrayList<HttpRequestInterceptor>());
-  
   private static class DynamicInterceptor implements HttpRequestInterceptor {
 
     @Override
@@ -151,7 +170,7 @@ public class HttpClientUtil {
 
     }
   }
-  
+
   public static void setHttpClientBuilder(SolrHttpClientBuilder newHttpClientBuilder) {
     httpClientBuilder = newHttpClientBuilder;
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientBuilder.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientBuilder.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientBuilder.java
index 7f3cf29..1bcf96b 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientBuilder.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientBuilder.java
@@ -138,8 +138,11 @@ public class Krb5HttpClientBuilder implements HttpClientBuilderFactory {
         });
         HttpClientUtil.addRequestInterceptor(bufferedEntityInterceptor);
       }
+    } else {
+      logger.warn("{} is configured without specifying system property '{}'",
+          getClass().getName(), LOGIN_CONFIG_PROP);
     }
-    
+
     return builder;
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveAuth.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveAuth.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveAuth.java
new file mode 100644
index 0000000..3334d9f
--- /dev/null
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveAuth.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.client.solrj.impl;
+
+import java.io.IOException;
+
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpRequestInterceptor;
+import org.apache.http.auth.AuthScheme;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.AuthState;
+import org.apache.http.auth.Credentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.protocol.ClientContext;
+import org.apache.http.protocol.HttpContext;
+
+/**
+ * This HTTP request interceptor adds HTTP authentication credentials to every outgoing
+ * request. This implementation is required since Solr client is not capable of performing
+ * non preemptive authentication. By adding the Http authentication credentials to every request,
+ * this interceptor enables "preemptive" authentication.
+ */
+public class PreemptiveAuth implements HttpRequestInterceptor {
+  private AuthScheme authScheme = null;
+
+  public PreemptiveAuth(AuthScheme authScheme) {
+    this.authScheme = authScheme;
+  }
+
+  @Override
+  public void process(final HttpRequest request, final HttpContext context) throws HttpException,
+      IOException {
+
+    AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
+    // If no auth scheme available yet, try to initialize it preemptively
+    if (authState.getAuthScheme() == null) {
+      CredentialsProvider credsProvider = (CredentialsProvider) context
+          .getAttribute(ClientContext.CREDS_PROVIDER);
+      Credentials creds = credsProvider.getCredentials(AuthScope.ANY);
+      authState.update(authScheme, creds);
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e1a57764/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthClientBuilderFactory.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthClientBuilderFactory.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthClientBuilderFactory.java
new file mode 100644
index 0000000..76ce990
--- /dev/null
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthClientBuilderFactory.java
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+
+package org.apache.solr.client.solrj.impl;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Optional;
+import java.util.Properties;
+
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.impl.auth.BasicScheme;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.solr.client.solrj.impl.SolrHttpClientBuilder.CredentialsProviderProvider;
+import org.apache.solr.common.params.MapSolrParams;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.StrUtils;
+
+/**
+ * HttpClientConfigurer implementation providing support for preemptive Http Basic authentication
+ * scheme.
+ */
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class PreemptiveBasicAuthClientBuilderFactory implements HttpClientBuilderFactory {
+  /**
+   * A system property used to specify a properties file containing default parameters used for
+   * creating a HTTP client. This is specifically useful for configuring the HTTP basic auth
+   * credentials (i.e. username/password). The name of the property must match the relevant
+   * Solr config property name.
+   */
+  public static final String SYS_PROP_HTTP_CLIENT_CONFIG = "solr.httpclient.config";
+
+  /**
+   * A system property to configure the Basic auth credentials via a java system property.
+   * Since this will expose the password on the command-line, it is not very secure. But
+   * this mechanism is added for backwards compatibility.
+   */
+  public static final String SYS_PROP_BASIC_AUTH_CREDENTIALS = "basicauth";
+
+  private static SolrParams defaultParams;
+  private static PreemptiveAuth requestInterceptor = new PreemptiveAuth(new BasicScheme());
+
+  static {
+    String credentials = System.getProperty(SYS_PROP_BASIC_AUTH_CREDENTIALS);
+    String configFile = System.getProperty(SYS_PROP_HTTP_CLIENT_CONFIG);
+
+    if (credentials != null && configFile != null) {
+      throw new RuntimeException("Basic authentication credentials passed via a configuration file"
+          + " as well as java system property. Please choose one mechanism!");
+    }
+
+    if (credentials != null) {
+      List<String> ss = StrUtils.splitSmart(credentials, ':');
+      if (ss.size() != 2) {
+        throw new RuntimeException("Please provide 'basicauth' in the 'user:password' format");
+      }
+      Properties defaultProps = new Properties();
+      defaultProps.setProperty(HttpClientUtil.PROP_BASIC_AUTH_USER, ss.get(0));
+      defaultProps.setProperty(HttpClientUtil.PROP_BASIC_AUTH_PASS, ss.get(1));
+      defaultParams = new MapSolrParams(new HashMap(defaultProps));
+    }
+
+    if(configFile != null) {
+      try {
+        Properties defaultProps = new Properties();
+        defaultProps.load(new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8));
+        defaultParams = new MapSolrParams(new HashMap(defaultProps));
+      } catch (IOException e) {
+        throw new IllegalArgumentException("Unable to read the Http client config file", e);
+      }
+    }
+  }
+
+  /**
+   * This method enables configuring system wide defaults (apart from using a config file based approach).
+   */
+  public static void setDefaultSolrParams(SolrParams params) {
+    defaultParams = params;
+  }
+
+  @Override
+  public void close() throws IOException {
+    HttpClientUtil.removeRequestInterceptor(requestInterceptor);
+  }
+
+  @Override
+  public SolrHttpClientBuilder getHttpClientBuilder(Optional<SolrHttpClientBuilder> builder) {
+    return builder.isPresent() ?
+        initHttpClientBuilder(builder.get())
+        : initHttpClientBuilder(SolrHttpClientBuilder.create());
+  }
+
+  private SolrHttpClientBuilder initHttpClientBuilder(SolrHttpClientBuilder builder) {
+    final String basicAuthUser = defaultParams.get(HttpClientUtil.PROP_BASIC_AUTH_USER);
+    final String basicAuthPass = defaultParams.get(HttpClientUtil.PROP_BASIC_AUTH_PASS);
+    if(basicAuthUser == null || basicAuthPass == null) {
+      throw new IllegalArgumentException("username & password must be specified with " + getClass().getName());
+    }
+
+    builder.setDefaultCredentialsProvider(new CredentialsProviderProvider() {
+      @Override
+      public CredentialsProvider getCredentialsProvider() {
+        CredentialsProvider credsProvider = new BasicCredentialsProvider();
+        credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(basicAuthUser, basicAuthPass));
+        return credsProvider;
+      }
+    });
+
+    HttpClientUtil.addRequestInterceptor(requestInterceptor);
+    return builder;
+  }
+}
\ No newline at end of file