You are viewing a plain text version of this content. The canonical link for it is here.
Posted to solr-user@lucene.apache.org by ddramireddy <dd...@gmail.com> on 2018/01/31 10:59:53 UTC

Using SolrJ for digest authentication

We are currently deploying Solr in war mode(Yes, recommendation is not war.
But this is something I can't change now. Planned for future). I am setting
authentication for solr. As Solr provided basic authentication is not
working in Solr 6.4.2, I am setting up digest authentication in tomcat for
Solr. I am able to login into Solr admin application using credentials.

Now from my Java application, when I try to run a query, which will delete
documents in a core, it's throwing following error.

org.apache.http.client.NonRepeatableRequestException: Cannot retry request
with a non-repeatable request entity

I can see in HttpSolrClient, we are setting only basic authentication. But,
I am using Digest auth. Did anyone faced this error before??

This is my code:

public static void main(String[] args) throws ClassNotFoundException,
SQLException, InterruptedException, IOException, SolrServerException {
        HttpSolrClient solrClient = getSolrHttpClient("solr",
"testpassword");

        try {
            solrClient.deleteByQuery("account", "*:*");
            solrClient.commit("account");
        } catch (final SolrServerException | IOException exn) {
            throw new IllegalStateException(exn);
        }
}

private static HttpSolrClient getSolrHttpClient(final String userName, final
String password) {

        final HttpSolrClient solrClient = new HttpSolrClient.Builder()
                .withBaseSolrUrl("http://localhost:9000/solr/index.html")
                .withHttpClient(getHttpClientWithSolrAuth(userName,
password))
                .build();

        return solrClient;
    }

    private static HttpClient getHttpClientWithSolrAuth(final String
userName, final String password) {
        final CredentialsProvider provider = new BasicCredentialsProvider();
        final UsernamePasswordCredentials credentials
                = new UsernamePasswordCredentials(userName, password);
        provider.setCredentials(AuthScope.ANY, credentials);


        return HttpClientBuilder.create()
                .addInterceptorFirst(new PreemptiveAuthInterceptor())
                .setDefaultCredentialsProvider(provider)
                .build();

    }


    static class PreemptiveAuthInterceptor implements HttpRequestInterceptor
{

        DigestScheme digestAuth = new DigestScheme();

        PreemptiveAuthInterceptor() {

        }

        @Override
        public void process(final HttpRequest request, final HttpContext
context)
                throws HttpException, IOException {
            final AuthState authState = (AuthState)
context.getAttribute(HttpClientContext.TARGET_AUTH_STATE);

            if (authState != null && authState.getAuthScheme() == null) {
                final CredentialsProvider credsProvider =
(CredentialsProvider)
context.getAttribute(HttpClientContext.CREDS_PROVIDER);
                final HttpHost targetHost = (HttpHost)
context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
                final Credentials creds = credsProvider.getCredentials(new
AuthScope(targetHost.getHostName(), targetHost.getPort(), "Solr",
"DIGEST"));
                if (creds == null) {
                    System.out.println("No credentials for preemptive
authentication");
                }
                digestAuth.overrideParamter("realm", "Solr");
                digestAuth.overrideParamter("nonce", Long.toString(new
Random().nextLong(), 36));
                AuthCache authCache = new BasicAuthCache();
                authCache.put(targetHost, digestAuth);

                // Add AuthCache to the execution context
                HttpClientContext localContext = HttpClientContext.create();
                localContext.setAuthCache(authCache);

                request.addHeader(digestAuth.authenticate(creds, request,
localContext));
            } else {
                System.out.println("authState is null. No preemptive
authentication.");
            }
        }
    }



--
Sent from: http://lucene.472066.n3.nabble.com/Solr-User-f472068.html

Re: Using SolrJ for digest authentication

Posted by ddramireddy <dd...@gmail.com>.
It's running only once. When request went from client from tomcat first-time,
tomcat sent response with "WWW-Authenticate" header with nonce value, asking
to complete the challenge. This challenge is processed. But apache http
client library is checking whether request is "repeatable" or not. This
validation is getting failed and following error is thrown.

"org.apache.http.client.NonRepeatableRequestException: Cannot retry request
with a non-repeatable request entity."

I am able to make POST call by directly calling apache http client library
with the following code. But, when I used solrj, I am getting this error.
"org.apache.http.client.NonRepeatableRequestException: Cannot retry request
with a non-repeatable request entity.". I can see solrj is setting
"isrepeatable" to false in httpsolrclient.java

Working code - When called directly using apache http library:

HttpHost target = HttpHost.create("localhost:9000");
        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(
                new AuthScope(target.getHostName(), target.getPort()),
                new UsernamePasswordCredentials("solr", "testpassword"));
        CloseableHttpClient httpclient = HttpClients.custom()
                .setDefaultCredentialsProvider(credsProvider)
                .build();
        try {

            AuthCache authCache = new BasicAuthCache();
            DigestScheme digestAuth = new DigestScheme();
            digestAuth.overrideParamter("realm", "Solr");
            authCache.put(target, digestAuth);

            // Add AuthCache to the execution context
            HttpClientContext localContext = HttpClientContext.create();
            localContext.setAuthCache(authCache);


            HttpPost httpPost = new
HttpPost("http://localhost:9000/solr/account/update?commit=true");
            httpPost.setHeader("Content-type", "text/xml");
            StringEntity stringEntity = new
StringEntity("<delete><query>*:*</query></delete>");
            httpPost.getRequestLine();
            httpPost.setEntity(stringEntity);
            System.out.println("Executing request " +
httpPost.getRequestLine() + " to target " + target);
            for (int i = 0; i < 3; i++) {
                CloseableHttpResponse response =
httpclient.execute(httpPost, localContext);
                try {
                   
System.out.println("----------------------------------------");
                    System.out.println(response.getStatusLine());
                   
System.out.println(EntityUtils.toString(response.getEntity()));
                } finally {
                    response.close();
                }
            }

        } finally {
            httpclient.close();
        } 


Failing code:


public class TestSolrWithDigest {
    public static void main(String[] args) {
        try {
            HttpSolrClient solrClient = initialiseSOLRClient();
            try {
            
                solrClient.deleteByQuery("account", "*:*");
                UpdateResponse updateResponse =
solrClient.commit("account");
                System.out.println(updateResponse.getStatus());
                System.out.println("completed");
                final ModifiableSolrParams pStatus = new
ModifiableSolrParams();
                pStatus.add("qt", "/dataimport");

                final QueryResponse resp = solrClient.query("account",
pStatus, SolrRequest.METHOD.GET);
                System.out.println("status:" + resp.getStatus());

            } catch (final SolrServerException | IOException exn) {

                throw new IllegalStateException(exn);
            }

        } catch (Exception e) {
            e.printStackTrace(System.err);
        }


    }

    private static HttpSolrClient initialiseSOLRClient() {
        URL solrURL = null;
        try {
            solrURL = new URL("http://localhost:9000/solr");
        } catch (MalformedURLException e) {
            System.out.println("Cannot parse the SOLR URL!!" +
"http://localhost:9000/solr");

        }
        String host = solrURL.getHost();
        int port = solrURL.getPort();

        AuthScope authScope = new AuthScope(host, port, "Solr", "Digest");

        UsernamePasswordCredentials creds = new
UsernamePasswordCredentials("solr", "testpassword");

        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(
                authScope,
                creds);

        HttpClientBuilder builder = create();
        builder.addInterceptorFirst(new PreemptiveAuthInterceptor());
        builder.setDefaultCredentialsProvider(credsProvider);
        CloseableHttpClient httpClient = builder.build();

        return new HttpSolrClient.Builder()
                .withBaseSolrUrl("http://localhost:9000/solr")
                .withHttpClient(httpClient)
                .build();
    }

    static class PreemptiveAuthInterceptor implements HttpRequestInterceptor
{

        public void process(final HttpRequest request, final HttpContext
context) throws HttpException, IOException {
           
            HttpEntity entity =
((HttpEntityEnclosingRequest)request).getEntity();


            HttpHost target = HttpHost.create("localhost:9000");
            CredentialsProvider credsProvider = new
BasicCredentialsProvider();
            credsProvider.setCredentials(
                    new AuthScope(target.getHostName(), target.getPort()),
                    new UsernamePasswordCredentials("solr",
"testpassword"));



            AuthCache authCache = new BasicAuthCache();
            DigestScheme digestAuth = new DigestScheme();
            digestAuth.overrideParamter("realm", "Solr");
            authCache.put(target, digestAuth);

            ((HttpClientContext)context).setAuthCache(authCache);

        }
    }
}



--
Sent from: http://lucene.472066.n3.nabble.com/Solr-User-f472068.html

Re: Using SolrJ for digest authentication

Posted by Rick Leir <rl...@leirtech.com>.
Eddy
Maybe your request is getting through twice. Check your logs to see.
Cheers -- Rick

On January 31, 2018 5:59:53 AM EST, ddramireddy <dd...@gmail.com> wrote:
>We are currently deploying Solr in war mode(Yes, recommendation is not
>war.
>But this is something I can't change now. Planned for future). I am
>setting
>authentication for solr. As Solr provided basic authentication is not
>working in Solr 6.4.2, I am setting up digest authentication in tomcat
>for
>Solr. I am able to login into Solr admin application using credentials.
>
>Now from my Java application, when I try to run a query, which will
>delete
>documents in a core, it's throwing following error.
>
>org.apache.http.client.NonRepeatableRequestException: Cannot retry
>request
>with a non-repeatable request entity
>
>I can see in HttpSolrClient, we are setting only basic authentication.
>But,
>I am using Digest auth. Did anyone faced this error before??
>
>This is my code:
>
>public static void main(String[] args) throws ClassNotFoundException,
>SQLException, InterruptedException, IOException, SolrServerException {
>        HttpSolrClient solrClient = getSolrHttpClient("solr",
>"testpassword");
>
>        try {
>            solrClient.deleteByQuery("account", "*:*");
>            solrClient.commit("account");
>        } catch (final SolrServerException | IOException exn) {
>            throw new IllegalStateException(exn);
>        }
>}
>
>private static HttpSolrClient getSolrHttpClient(final String userName,
>final
>String password) {
>
>        final HttpSolrClient solrClient = new HttpSolrClient.Builder()
>              .withBaseSolrUrl("http://localhost:9000/solr/index.html")
>                .withHttpClient(getHttpClientWithSolrAuth(userName,
>password))
>                .build();
>
>        return solrClient;
>    }
>
>    private static HttpClient getHttpClientWithSolrAuth(final String
>userName, final String password) {
>   final CredentialsProvider provider = new BasicCredentialsProvider();
>        final UsernamePasswordCredentials credentials
>                = new UsernamePasswordCredentials(userName, password);
>        provider.setCredentials(AuthScope.ANY, credentials);
>
>
>        return HttpClientBuilder.create()
>                .addInterceptorFirst(new PreemptiveAuthInterceptor())
>                .setDefaultCredentialsProvider(provider)
>                .build();
>
>    }
>
>
>static class PreemptiveAuthInterceptor implements
>HttpRequestInterceptor
>{
>
>        DigestScheme digestAuth = new DigestScheme();
>
>        PreemptiveAuthInterceptor() {
>
>        }
>
>        @Override
>       public void process(final HttpRequest request, final HttpContext
>context)
>                throws HttpException, IOException {
>            final AuthState authState = (AuthState)
>context.getAttribute(HttpClientContext.TARGET_AUTH_STATE);
>
>          if (authState != null && authState.getAuthScheme() == null) {
>                final CredentialsProvider credsProvider =
>(CredentialsProvider)
>context.getAttribute(HttpClientContext.CREDS_PROVIDER);
>                final HttpHost targetHost = (HttpHost)
>context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
>             final Credentials creds = credsProvider.getCredentials(new
>AuthScope(targetHost.getHostName(), targetHost.getPort(), "Solr",
>"DIGEST"));
>                if (creds == null) {
>                    System.out.println("No credentials for preemptive
>authentication");
>                }
>                digestAuth.overrideParamter("realm", "Solr");
>                digestAuth.overrideParamter("nonce", Long.toString(new
>Random().nextLong(), 36));
>                AuthCache authCache = new BasicAuthCache();
>                authCache.put(targetHost, digestAuth);
>
>                // Add AuthCache to the execution context
>           HttpClientContext localContext = HttpClientContext.create();
>                localContext.setAuthCache(authCache);
>
>              request.addHeader(digestAuth.authenticate(creds, request,
>localContext));
>            } else {
>                System.out.println("authState is null. No preemptive
>authentication.");
>            }
>        }
>    }
>
>
>
>--
>Sent from: http://lucene.472066.n3.nabble.com/Solr-User-f472068.html

-- 
Sorry for being brief. Alternate email is rickleir at yahoo dot com