如何在SolrJ-CloudSolrClient中进行BasicAuthentication?

时间:2018-10-28 07:42:35

标签: solr solrj solrcloud

我正在使用Solr 7.5 Server,并且曾经使用过外部Zookeeper。当我使用Solr Admin UI浏览时,它会要求我进行身份验证。

对于Java客户端,我使用了以下代码

    BasicAuthSolrClientCache bs = new BasicAuthSolrClientCache("solr", "SolrRocks");

    CloudSolrClient solrCloudClient = bs.getCloudSolrClient(zkHost);
    solrCloudClient.setDefaultCollection("sample");

    SolrInputDocument doc = new SolrInputDocument();
    doc.addField("cat", "book");
    doc.addField("id", "book-1");
    doc.addField("name", "The Legend of the Hobbit part 1");
    solrCloudClient.add(doc);
    solrCloudClient.commit();
    solrCloudClient.close();

BasicAuthSolrClientCache.java

 public class BasicAuthSolrClientCache extends SolrClientCache {

 private static final Logger log = 
 LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

 private final Map<String, SolrClient> solrClients = new HashMap<>();
 private final String username;
 private final String password;

 public BasicAuthSolrClientCache(String username, String password) {
 this.username = username;
 this.password = password;
}

@Override
public synchronized CloudSolrClient getCloudSolrClient(String zkHost) {
CloudSolrClient client;
if (solrClients.containsKey(zkHost)) {
  client = (CloudSolrClient) solrClients.get(zkHost);
} else {
  client = new CloudSolrClient.Builder()
      .withZkHost(zkHost)
      .withHttpClient(getHttpClient())
      .build();
  client.connect();
  solrClients.put(zkHost, client);
}

return client;

}

 @Override
 public synchronized HttpSolrClient getHttpSolrClient(String host) {
  HttpSolrClient client;
  if (solrClients.containsKey(host)) {
   client = (HttpSolrClient) solrClients.get(host);
  } else {
  client = new HttpSolrClient.Builder(host)
      .withHttpClient(getHttpClient())
      .build();
   solrClients.put(host, client);
  }
 return client;
}

@Override
public synchronized void close() {
 for(Map.Entry<String, SolrClient> entry : solrClients.entrySet()) {
  try {
    entry.getValue().close();
  } catch (IOException e) {
    log.error("Error closing SolrClient for " + entry.getKey(), e);
  }
}
solrClients.clear();
}

private HttpClient getHttpClient() {
 CredentialsProvider provider = new BasicCredentialsProvider();
 UsernamePasswordCredentials credentials = new 
 UsernamePasswordCredentials(this.username, this.password);
 provider.setCredentials(AuthScope.ANY, credentials);
 return 


HttpClientBuilder.create().setDefaultCredentialsProvider(provider).
build();
 }
}

但是它给出了如下异常,

  

线程“ main”中的异常org.apache.solr.client.solrj.impl.CloudSolrClient $ RouteException:与位于

http://192.168.0.104:8983/solr/gettingstarted_shard2_replica1处的服务器通信时发生IOException

如何使用SolrJ对SolrCloud进行身份验证

2 个答案:

答案 0 :(得分:1)

您还可以将UpdateRequest用于索引请求,以通过SolrJ进行基本身份验证:

UpdateRequest ur = new UpdateRequest();
ur.add(doc);
ur.setBasicAuthCredentials("YOU USER NAME", "USER PASSWORD");
ur.setCommitWithin(COMMIT_WITHIN_INTERVAL);
ur.process(cloudSolrClient);

答案 1 :(得分:0)

我找到了一种简单的方法。

您可以添加这样的请求拦截器,因此您不必担心自己创建正确配置的HttpClient实例。这只会将拦截器添加到Solrj创建的默认HttpClient中。

org.apache.solr.client.solrj.impl.HttpClientUtil.addRequestInterceptor(new SolrPreemptiveAuthInterceptor());

RequestInterceptor看起来像这样:

public class SolrPreemptiveAuthInterceptor implements HttpRequestInterceptor {

    final static Logger log = LoggerFactory.getLogger(SolrPreemptiveAuthInterceptor.class); 

    @Override
    public void process(HttpRequest request, 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) {
                log.info("No AuthState: set Basic Auth");

                HttpHost targetHost = (HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
                AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());

                CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(HttpClientContext.CREDS_PROVIDER);

                Credentials creds = credsProvider.getCredentials(authScope);
                if(creds == null){
                    log.info("No Basic Auth credentials: add them");
                    creds = getCredentials(authScope);
                }
                authState.update(new BasicScheme(), creds);
            }

    }


    private Credentials getCredentials(AuthScope authScope) {

        String user = "";
        String password = "";
        UsernamePasswordCredentials creds = new UsernamePasswordCredentials(user, password);

        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(authScope, creds);
        log.info("Creating Basic Auth credentials for user {}", user);

        return credsProvider.getCredentials(authScope);
    }
}