关于Solr基本认证的几种坑爹认证

不得不说,Solr这个组件的坑很多,能使用Elasticsearch就尽量别使用Solr。
如果在使用Solr的过程中出现401错误,一般就是因为Solr开启了基本认证。注意:是基本认证,不是Kerberos认证!
首先是CDH版本的4.10.3的Solr添加基本认证登录之后的增删改查。

    private static void loginSolr(String username,String password) {
        HttpClientUtil.setConfigurer(new PreemptiveBasicAuthConfigurer());
        ModifiableSolrParams params = new ModifiableSolrParams();
        params.set(HttpClientUtil.PROP_BASIC_AUTH_USER,username);
        params.set(HttpClientUtil.PROP_BASIC_AUTH_PASS, password);
    }

通过该方法,将用户和密码传入即可进行查询修改。
如果是通过HttpSolrServer进行连接的solr,那么就需要进行另一种认证方式,是HttpClient的抢先认证。

 HttpSolrServer server = new HttpSolrServer("http://hadoop01:8983/solr/collection1");
        HttpClientUtil.setBasicAuth((DefaultHttpClient) server.getHttpClient(), "user", "pass");
        DefaultHttpClient m_client =(DefaultHttpClient)server.getHttpClient();
        UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("user", "pass");

        m_client.addRequestInterceptor(new PreemptiveAuthInterceptor(),0);
        m_client.getCredentialsProvider().setCredentials(new AuthScope("hadoop01",8983), credentials);
        server.setRequestWriter(new BinaryRequestWriter());
        server.setAllowCompression(true);

该种方法必须单另创建一个类如下:

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);
            }
        }
    }

在你认证过程中如果出现这种报错:

Caused by: org.apache.http.client.ClientProtocolException: null
	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:187)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
	at org.apache.solr.client.solrj.impl.HttpSolrClient.executeMethod(HttpSolrClient.java:564)
	... 12 common frames omitted
Caused by: org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity.
	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:225)
	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
	at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
	... 15 common frames omitted

那么证明你的认证程序大致方向是对的。需要进一步调整某些对象。

在Solr官网,目前提供的认证方式就是

SolrRequest req ;//create a new request object
req.setBasicAuthCredentials(userName, password);
solrClient.request(req);
QueryRequest req = new QueryRequest(new SolrQuery("*:*"));
req.setBasicAuthCredentials(userName, password);
QueryResponse rsp = req.process(solrClient);

我只能说,这个根本没屌用。只支持Solr5以上的,而且对于HttpSolrServer的一些其他操作,根本不起作用。局限性大的一批…

接下来是Solr5.X以上的版本的基本认证。
上面的那个登录的方法还是可以用的,但是需要重新添加两个类,因为Solr5.x没有那两个类,而且官方也没说更新版本之后PreemptiveBasicAuthConfigurer类被什么替换了。
其次是官方给的方法:

CloudSolrClient client = new CloudSolrClient(zkHost);
client.setDefaultCollection("collection1");
SolrQuery query = new SolrQuery();
query.set("q","*:*");
QueryRequest req = new QueryRequest(query);
req.setBasicAuthCredentials("username","password");
QueryResponse rsp = req.process(client);
SolrDocumentList list = rsp.getResults();

最后是Solr5.X之后的HttpSolrClient的基本认证:
在HttpSolrClient下面进行抢先认证:

    UsernamePasswordCredentials creds = new UsernamePasswordCredentials(config.getUser(), config.getPassword());
        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(
                AuthScope.ANY,
                creds);

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

        client = new HttpSolrClient.Builder().withBaseSolrUrl(config.getSolrUrl())
                .withHttpClient(httpClient)
                .build();
class PreemptiveAuthInterceptor implements HttpRequestInterceptor {
    public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
        AuthState authState = (AuthState) context.getAttribute(HttpClientContext.TARGET_AUTH_STATE);
        // If no auth scheme available yet, try to initialize it
        // preemptively
        if (authState.getAuthScheme() == null) {
            CredentialsProvider credsProvider = (CredentialsProvider)
                    context.getAttribute(HttpClientContext.CREDS_PROVIDER);
            HttpHost targetHost = (HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
            AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());
            Credentials creds = credsProvider.getCredentials(authScope);
            if(creds == null){
            }
            authState.update(new BasicScheme(), creds);
        }
    }
}

也有人提供这种方式:

  CredentialsProvider provider = new BasicCredentialsProvider();
        if (config.hasCredentials()) {
            UsernamePasswordCredentials credentials
                    = new UsernamePasswordCredentials(config.getUser(), config.getPassword());
            provider.setCredentials(AuthScope.ANY, credentials);
        }
        HttpClient httpClient = HttpClientBuilder.create()
                                             .setDefaultCredentialsProvider(provider)
                                             .build();
        try (HttpSolrClient client = new HttpSolrClient.Builder().withBaseSolrUrl(config.getSolrUrl())
                                                                 .withHttpClient(httpClient)
                                                                 .build()) {

具体还是需要多次尝试。。。

你可能感兴趣的:(Solr,SolrCloud)