Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Using SolrJ with BASIC Authentication and SSL Wrapped Solr

DZone's Guide to

Using SolrJ with BASIC Authentication and SSL Wrapped Solr

· Big Data Zone
Free Resource

See how the beta release of Kubernetes on DC/OS 1.10 delivers the most robust platform for building & operating data-intensive, containerized apps. Register now for tech preview.

Do you have BASIC authentication turned on for Solr? Are you using a self signed SSL Certificate? Do you want to index to this server using SolrJ? I’ve taken a couple of tries to get all the magic incantations to work, but finally have done it. Hopefully this saves you some of the pain I experienced in searching around StackOverflow and random blog posts.

Some of the error messages you might get are:

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated or unauthorized access.
To sum it up, you have to fake out the certificate checking and then wrap your HTTP call with something called Preemptive Authentication.

You can get the method here.

package com.o19s.http;

import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;

public class InsecureHttpClient implements HttpClient {

  private HttpClient httpClient;

	/**
	 * This class allows you to access the Solr servers that are running under
	 * SSL certificates and using BASIC authentication. However, the SSL
	 * certificates are self signed, and therefore will generate a
	 * "peer cannot be verified" error. This works around it. Additionally, to
	 * make BASIC auth all work on a single request you need a Preemptive
	 * Authenticator.
	 * 
	 * The equivalent in curl is curl --user admin:password --insecure "https://localhost:443/solr/update/?commit=true"
	 * 
	 * @param httpClient  The client all calls are delegated to
	 * @param username
	 * @param password
	 */
	public InsecureHttpClient(HttpClient httpClient, String username, String password) throws Exception {

		super();

		SSLContext ctx = SSLContext.getInstance("TLS");
		X509TrustManager tm = new X509TrustManager() {

			public void checkClientTrusted(X509Certificate[] xcs, String string) {
			}

			@Override
			public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
			}

			public java.security.cert.X509Certificate[] getAcceptedIssuers() {
				return null;
			}

		};
		X509HostnameVerifier verifier = new X509HostnameVerifier() {

			@Override
			public void verify(String string, SSLSocket ssls) throws IOException {
			}

			@Override
			public void verify(String string, X509Certificate xc) throws SSLException {
			}

			@Override
			public void verify(String string, String[] strings, String[] strings1) throws SSLException {
			}

			@Override
			public boolean verify(String string, SSLSession ssls) {
				return true;
			}
		};
		ctx.init(null, new TrustManager[] { tm }, null);
		SSLSocketFactory ssf = new SSLSocketFactory(ctx);
		ssf.setHostnameVerifier(verifier);
		ClientConnectionManager ccm = httpClient.getConnectionManager();
		SchemeRegistry sr = ccm.getSchemeRegistry();
		sr.register(new Scheme("https", ssf, 443));
		DefaultHttpClient wrappedClient = new DefaultHttpClient(ccm, httpClient.getParams());

		if (username != null && username.length() > 0) {
			wrappedClient.addRequestInterceptor(new PreEmptiveBasicAuthenticator(username, password));
		}

		this.httpClient = wrappedClient;

	}

	public HttpResponse execute(HttpHost arg0, HttpRequest arg1, HttpContext arg2) throws IOException, ClientProtocolException {
		return httpClient.execute(arg0, arg1, arg2);
	}

	public <T> T execute(HttpHost arg0, HttpRequest arg1, ResponseHandler<? extends T> arg2, HttpContext arg3) throws IOException, ClientProtocolException {
		return httpClient.execute(arg0, arg1, arg2, arg3);
	}

	public <T> T execute(HttpHost arg0, HttpRequest arg1, ResponseHandler<? extends T> arg2) throws IOException, ClientProtocolException {
		return httpClient.execute(arg0, arg1, arg2);
	}

	public HttpResponse execute(HttpHost arg0, HttpRequest arg1) throws IOException, ClientProtocolException {
		return httpClient.execute(arg0, arg1);
	}

	public HttpResponse execute(HttpUriRequest arg0, HttpContext arg1) throws IOException, ClientProtocolException {
		return httpClient.execute(arg0, arg1);
	}

	public <T> T execute(HttpUriRequest arg0, ResponseHandler<? extends T> arg1, HttpContext arg2) throws IOException, ClientProtocolException {
		return httpClient.execute(arg0, arg1, arg2);
	}

	public <T> T execute(HttpUriRequest arg0, ResponseHandler<? extends T> arg1) throws IOException, ClientProtocolException {
		return httpClient.execute(arg0, arg1);
	}

	public HttpResponse execute(HttpUriRequest arg0) throws IOException, ClientProtocolException {
		return httpClient.execute(arg0);
	}

	public ClientConnectionManager getConnectionManager() {
		return httpClient.getConnectionManager();
	}

	public HttpParams getParams() {
		return httpClient.getParams();
	}

	public class PreEmptiveBasicAuthenticator implements HttpRequestInterceptor {
		  private final UsernamePasswordCredentials credentials;

		  public PreEmptiveBasicAuthenticator(String user, String pass) {
		    credentials = new UsernamePasswordCredentials(user, pass);
		  }

		  @Override
		  public void process(HttpRequest request, HttpContext context)
		      throws HttpException, IOException {
		    request.addHeader(BasicScheme.authenticate(credentials,"US-ASCII",false));
		  }
		}
}
To use this class, just pass in your regular client and username/password combo:

ModifiableSolrParams params = new ModifiableSolrParams();
params.set(HttpClientUtil.PROP_MAX_CONNECTIONS, 128);
params.set(HttpClientUtil.PROP_MAX_CONNECTIONS_PER_HOST, 32);
params.set(HttpClientUtil.PROP_FOLLOW_REDIRECTS, false);
HttpClient httpClient = HttpClientUtil.createClient(params);
httpClient = new InsecureHttpClient(httpClient, username, password);
SolrServer solrServer = new HttpSolrServer(url, httpClient));
By the way, the equivalent of all of this in curl is:

curl --user admin:password --insecure "https://localhost:443/solr/update/?commit=true"

New Mesosphere DC/OS 1.10: Production-proven reliability, security & scalability for fast-data, modern apps. Register now for a live demo.

Topics:

Published at DZone with permission of Eric Pugh, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}