Search code examples
authenticationsolrjettybasic-authenticationjetty-8

Solr 4 with basic authentication


I am trying to connect to solr using solrj. My solr instance runs in jetty and is protected with basic authentication. I found these links that contain relevant information.

http://grokbase.com/t/lucene/solr-user/1288xjjbwx/http-basic-authentication-with-httpsolrserver

Preemptive Basic authentication with Apache HttpClient 4 However, I still get the following exception:

Caused by: org.apache.http.client.ClientProtocolException
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:822)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732)
at org.apache.solr.client.solrj.impl.HttpSolrServer.request(HttpSolrServer.java:352)
... 5 more
 Caused by: org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity.
at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:625)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:464)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
... 8 more

I have also attached a snippet of the code I am using.

public static void main(String[] args) throws SolrServerException, IOException {

    HttpSolrServer server = new HttpSolrServer("http://localhost:8983/solr/");

    DefaultHttpClient m_client =(DefaultHttpClient)server.getHttpClient(); 
    UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(USERNAME, PASSWORD);

    m_client.addRequestInterceptor(new PreemptiveAuthInterceptor(),0);
    (((DefaultHttpClient)m_client).getCredentialsProvider()).setCredentials(new AuthScope("localhost",8983), credentials);

    SolrInputDocument document = new SolrInputDocument();
    document.addField("id",123213);
    server.add(document);
    server.commit();

}

}

class PreemptiveAuthInterceptor implements HttpRequestInterceptor {

    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 avaialble yet, try to initialize it
        // preemptively
        if (authState.getAuthScheme() == null) {
            AuthScheme authScheme = (AuthScheme) context.getAttribute("preemptive-auth");
            CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(ClientContext.CREDS_PROVIDER);
            HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
            if (authScheme != null) {
                Credentials creds = credsProvider.getCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()));
                if (creds == null) {
                    throw new HttpException("No credentials for preemptive authentication");
                }
                authState.setAuthScheme(authScheme);
                authState.setCredentials(creds);
            }
        }

    }

Can anyone point me in the right direction? Thanks !!


Solution

  • i had the same problem when implementing partial documents update. i solved the problem by implementing PreemptiveAuthInterceptor. see below code

    PoolingClientConnectionManager cxMgr = new PoolingClientConnectionManager(
                            SchemeRegistryFactory.createDefault());
                    cxMgr.setMaxTotal(100);
                    cxMgr.setDefaultMaxPerRoute(20);
    
                    DefaultHttpClient httpclient = new DefaultHttpClient(cxMgr);
                    httpclient.addRequestInterceptor(
                            new PreemptiveAuthInterceptor(), 0);
                    httpclient.getCredentialsProvider().setCredentials(
                            AuthScope.ANY,
                            new UsernamePasswordCredentials(solrDto.getUsername(),
                                    solrDto.getPassword()));
    
                    HttpSolrServer solrServerInstance = new HttpSolrServer(solrDto.getUrl(),
                            httpclient);
                    solrServerInstance.setRequestWriter(new BinaryRequestWriter());
                    solrServerInstance.setAllowCompression(true);
    

    You also need:

        private class PreemptiveAuthInterceptor implements HttpRequestInterceptor {
    
                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 avaialble yet, try to initialize it
                    // preemptively
                    if (authState.getAuthScheme() == null) {
                        CredentialsProvider credsProvider = (CredentialsProvider) context
                                .getAttribute(ClientContext.CREDS_PROVIDER);
                        HttpHost targetHost = (HttpHost) context
                                .getAttribute(ExecutionContext.HTTP_TARGET_HOST);
                        Credentials creds = credsProvider.getCredentials(new AuthScope(
                                targetHost.getHostName(), targetHost.getPort()));
                        if (creds == null)
                            throw new HttpException(
                                    "No credentials for preemptive authentication");
                        authState.setAuthScheme(new BasicScheme());
                        authState.setCredentials(creds);
                    }
    
                }
    
            }