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