lucene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From markrmil...@apache.org
Subject [2/2] lucene-solr:branch_6x: SOLR-9997: Enable configuring SolrHttpClientBuilder via java system property.
Date Mon, 13 Feb 2017 17:26:49 GMT
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/a986368f
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/a986368f
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/a986368f

Branch: refs/heads/branch_6x
Commit: a986368fd0670840177a8c19fb15dcd1f0e69797
Parents: c19dff9
Author: markrmiller <markrmiller@apache.org>
Authored: Mon Feb 13 12:21:19 2017 -0500
Committer: markrmiller <markrmiller@apache.org>
Committed: Mon Feb 13 12:21:19 2017 -0500

----------------------------------------------------------------------
 solr/CHANGES.txt                                |   2 +
 solr/bin/solr                                   |  29 ++++-
 solr/bin/solr.cmd                               |  33 +++++-
 solr/bin/solr.in.cmd                            |   4 +-
 solr/bin/solr.in.sh                             |   6 +-
 .../apache/solr/security/HadoopAuthPlugin.java  |  36 +++++++
 .../src/java/org/apache/solr/util/SolrCLI.java  |  39 -------
 .../solr/client/solrj/impl/HttpClientUtil.java  |  24 ++++-
 .../solrj/impl/Krb5HttpClientConfigurer.java    |   3 +
 .../solr/client/solrj/impl/PreemptiveAuth.java  |  59 +++++++++++
 .../impl/PreemptiveBasicAuthConfigurer.java     | 106 +++++++++++++++++++
 11 files changed, 295 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a986368f/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index d74e074..57f860e 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -53,6 +53,8 @@ New Features
 * SOLR-9916: Adds Stream Evaluators to support evaluating values from tuples. Supports boolean,
   numeric, and conditional evaluators. BooleanOperations have been removed in preference
of
   BooleanEvaluators. (Dennis Gove)
+
+* SOLR-9997: Enable configuring SolrHttpClientBuilder via java system property. (Hrishikesh
Gadre via Mark Miller)
  
 Optimizations
 ----------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a986368f/solr/bin/solr
----------------------------------------------------------------------
diff --git a/solr/bin/solr b/solr/bin/solr
index 7f154fc..ffbd5db 100755
--- a/solr/bin/solr
+++ b/solr/bin/solr
@@ -232,8 +232,35 @@ 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_CONFIGURER" ]; then
+  echo "WARNING: SOLR_AUTHENTICATION_CLIENT_CONFIGURER 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_CONFIGURER 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_CONFIGURER="org.apache.solr.client.solrj.impl.PreemptiveBasicAuthConfigurer"
+      ;;
+    kerberos)
+      SOLR_AUTHENTICATION_CLIENT_CONFIGURER="org.apache.solr.client.solrj.impl.Krb5HttpClientConfigurer"
+      ;;
+    *)
+      echo "ERROR: Value specified for SOLR_AUTH_TYPE environment variable is invalid."
+      exit 1
+   esac
+fi
+
 if [ "$SOLR_AUTHENTICATION_CLIENT_CONFIGURER" != "" ]; then
-  AUTHC_CLIENT_CONFIGURER_ARG="-Dsolr.authentication.httpclient.configurer=$SOLR_AUTHENTICATION_CLIENT_CONFIGURER"
+  AUTHC_CLIENT_CONFIGURER_ARG="-Dsolr.httpclient.builder.factory=$SOLR_AUTHENTICATION_CLIENT_CONFIGURER"
 fi
 AUTHC_OPTS="$AUTHC_CLIENT_CONFIGURER_ARG $SOLR_AUTHENTICATION_OPTS"
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a986368f/solr/bin/solr.cmd
----------------------------------------------------------------------
diff --git a/solr/bin/solr.cmd b/solr/bin/solr.cmd
index 84192a4..0ca0c3b 100644
--- a/solr/bin/solr.cmd
+++ b/solr/bin/solr.cmd
@@ -117,8 +117,39 @@ 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_CONFIGURER (
+    echo WARNING: SOLR_AUTHENTICATION_CLIENT_CONFIGURER 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_CONFIGURER configuration variable
will be ignored
+  )
+)
+
+IF DEFINED SOLR_AUTH_TYPE (
+  IF /I "%SOLR_AUTH_TYPE%" == "basic" (
+    set SOLR_AUTHENTICATION_CLIENT_CONFIGURER="org.apache.solr.client.solrj.impl.PreemptiveBasicAuthConfigurer"
+  ) ELSE (
+    IF /I "%SOLR_AUTH_TYPE%" == "kerberos" (
+      set SOLR_AUTHENTICATION_CLIENT_CONFIGURER="org.apache.solr.client.solrj.impl.Krb5HttpClientConfigurer"
+    ) ELSE (
+      echo ERROR: Value specified for SOLR_AUTH_TYPE configuration variable is invalid.
+      goto err
+    )
+  )
+)
+
 IF DEFINED SOLR_AUTHENTICATION_CLIENT_CONFIGURER (
-  set AUTHC_CLIENT_CONFIGURER_ARG="-Dsolr.authentication.httpclient.configurer=%SOLR_AUTHENTICATION_CLIENT_CONFIGURER%"
+  set AUTHC_CLIENT_CONFIGURER_ARG="-Dsolr.httpclient.builder.factory=%SOLR_AUTHENTICATION_CLIENT_CONFIGURER%"
 )
 set "AUTHC_OPTS=%AUTHC_CLIENT_CONFIGURER_ARG% %SOLR_AUTHENTICATION_OPTS%"
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a986368f/solr/bin/solr.in.cmd
----------------------------------------------------------------------
diff --git a/solr/bin/solr.in.cmd b/solr/bin/solr.in.cmd
index d400773..59dee18 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_CONFIGURER=
+REM Please configure only one of SOLR_AUTHENTICATION_CLIENT_CONFIGURER or SOLR_AUTH_TYPE
parameters
+REM set SOLR_AUTHENTICATION_CLIENT_CONFIGURER=org.apache.solr.client.solrj.impl.PreemptiveBasicAuthConfigurer
+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/a986368f/solr/bin/solr.in.sh
----------------------------------------------------------------------
diff --git a/solr/bin/solr.in.sh b/solr/bin/solr.in.sh
index 5ca483f..7b4d21c 100644
--- a/solr/bin/solr.in.sh
+++ b/solr/bin/solr.in.sh
@@ -120,8 +120,10 @@
 #SOLR_SSL_CLIENT_TRUST_STORE_TYPE=
 
 # Settings for authentication
-#SOLR_AUTHENTICATION_CLIENT_CONFIGURER=
-#SOLR_AUTHENTICATION_OPTS=
+# Please configure only one of SOLR_AUTHENTICATION_CLIENT_CONFIGURER or SOLR_AUTH_TYPE parameters
+#SOLR_AUTHENTICATION_CLIENT_CONFIGURER="org.apache.solr.client.solrj.impl.PreemptiveBasicAuthConfigurer"
+#SOLR_AUTH_TYPE="basic"
+#SOLR_AUTHENTICATION_OPTS="-Dbasicauth=solr:SolrRocks"
 
 # Settings for ZK ACL
 #SOLR_ZK_CREDS_AND_ACLS="-DzkACLProvider=org.apache.solr.common.cloud.VMParamsAllAndReadonlyDigestZkACLProvider
\

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a986368f/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 925a886..68a8585 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;
 
@@ -114,6 +115,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;
 
@@ -206,6 +213,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" +
@@ -221,6 +245,18 @@ 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/a986368f/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 0c43049..7a3733c 100644
--- a/solr/core/src/java/org/apache/solr/util/SolrCLI.java
+++ b/solr/core/src/java/org/apache/solr/util/SolrCLI.java
@@ -61,7 +61,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;
@@ -81,14 +80,12 @@ 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;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
-import org.apache.solr.client.solrj.impl.HttpClientConfigurer;
 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;
@@ -107,7 +104,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;
@@ -115,7 +111,6 @@ import org.noggit.ObjectBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.apache.solr.common.SolrException.ErrorCode.FORBIDDEN;
 import static org.apache.solr.common.SolrException.ErrorCode.UNAUTHORIZED;
 import static org.apache.solr.common.params.CommonParams.NAME;
@@ -154,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
@@ -262,19 +256,6 @@ public class SolrCLI {
   }
 
   public static CommandLine parseCmdLine(String[] args, Option[] toolOptions) throws Exception
{
-    String configurerClassName = System.getProperty("solr.authentication.httpclient.configurer");
-    if (configurerClassName!=null) {
-      try {
-        Class c = Class.forName(configurerClassName);
-        HttpClientConfigurer configurer = (HttpClientConfigurer)c.newInstance();
-        HttpClientUtil.setConfigurer(configurer);
-        log.info("Set HttpClientConfigurer from: "+configurerClassName);
-      } catch (Exception ex) {
-        log.error(ex.getMessage());
-        throw new RuntimeException("Error during loading of configurer '"+configurerClassName+"'.",
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. 
    */
@@ -3342,7 +3304,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/a986368f/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 b8b7400..2a66ad8 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
@@ -91,7 +91,13 @@ public class HttpClientUtil {
   public static final String PROP_BASIC_AUTH_PASS = "httpBasicAuthPassword";
   
   public static final String SYS_PROP_CHECK_PEER_NAME = "solr.ssl.checkPeerName";
-  
+
+  /**
+   * A Java system property to select the {@linkplain HttpClientConfigurer} used for
+   * configuring the {@linkplain HttpClientConfigurer} instance by default.
+   */
+  public static final String SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY = "solr.httpclient.builder.factory";
+
   private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
   
   static final DefaultHttpRequestRetryHandler NO_RETRY = new DefaultHttpRequestRetryHandler(
@@ -101,7 +107,21 @@ public class HttpClientUtil {
       = Collections.synchronizedList(new ArrayList<>(singletonList(new HttpClientConfigurer())));
 
   private static final List<HttpRequestInterceptor> interceptors = Collections.synchronizedList(new
ArrayList<>());
-  
+
+  static {
+    // 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 {
+        HttpClientConfigurer factory = (HttpClientConfigurer)Class.forName(factoryClassName).newInstance();
+        addConfigurer(factory);
+      } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e)
{
+        throw new RuntimeException("Unable to instantiate Solr HttpClientBuilderFactory",
e);
+      }
+    }
+  }
+
   /**
    * Add a {@link HttpClientConfigurer} class used to configure the http
    * clients.

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a986368f/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientConfigurer.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientConfigurer.java
b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientConfigurer.java
index ab336e9..dbb339c 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientConfigurer.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Krb5HttpClientConfigurer.java
@@ -112,6 +112,9 @@ public class Krb5HttpClientConfigurer extends HttpClientConfigurer {
       } else {
         httpClient.getCredentialsProvider().clear();
       }
+    } else {
+      logger.warn("{} is configured without specifying system property '{}'",
+                    getClass().getName(), LOGIN_CONFIG_PROP);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a986368f/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/a986368f/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthConfigurer.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthConfigurer.java
b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthConfigurer.java
new file mode 100644
index 0000000..33835d1
--- /dev/null
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthConfigurer.java
@@ -0,0 +1,106 @@
+/*
+ * 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.Properties;
+
+import org.apache.http.impl.auth.BasicScheme;
+import org.apache.http.impl.client.DefaultHttpClient;
+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 PreemptiveBasicAuthConfigurer extends HttpClientConfigurer {
+  /**
+   * 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;
+
+  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 configure(DefaultHttpClient httpClient, SolrParams config) {
+    config = SolrParams.wrapDefaults(config, defaultParams);
+    final String basicAuthUser = config.get(HttpClientUtil.PROP_BASIC_AUTH_USER);
+    final String basicAuthPass = config.get(HttpClientUtil.PROP_BASIC_AUTH_PASS);
+    if(basicAuthUser == null || basicAuthPass == null) {
+      throw new IllegalArgumentException("username & password must be specified with
" + getClass().getName());
+    }
+    super.configure(httpClient, config);
+    httpClient.addRequestInterceptor(new PreemptiveAuth(new BasicScheme()), 0);
+  }
+}
\ No newline at end of file


Mime
View raw message