【问题标题】:Solrj Authentication Fails On Write OperationSolrj 身份验证在写入操作时失败
【发布时间】:2014-11-09 05:20:44
【问题描述】:

Jetty 服务器上只有密码保护的 solr。我可以使用 solrj 从 solr 读取/访问数据:->

HttpSolrServer solr = new HttpSolrServer("http://111.111.111:8983/solr/mysolr");
   HttpClientUtil.setBasicAuth((DefaultHttpClient) solr.getHttpClient(), "admin", "akshaybhatt");

但它给了我如下 I/O 异常。 SO上有关于authentication的其他示例,但我不知道如何在Solrj中使用身份验证。以下错误仅在我尝试更新记录时出现(并可能添加记录,尚未测试)

org.apache.solr.client.solrj.SolrServerException: IOException occured when talking to server at: http://111.111.111.138:8983/solr/mysolrcore
    at org.apache.solr.client.solrj.impl.HttpSolrServer.request(HttpSolrServer.java:507)
    at org.apache.solr.client.solrj.impl.HttpSolrServer.request(HttpSolrServer.java:199)
    at org.apache.solr.client.solrj.request.AbstractUpdateRequest.process(AbstractUpdateRequest.java:118)
    at org.apache.solr.client.solrj.SolrServer.add(SolrServer.java:116)
    at org.apache.solr.client.solrj.SolrServer.add(SolrServer.java:102)
    at UpdateSolrTesting.AddToSolr(UpdateSolrTesting.java:228)
    at UpdateSolrTesting.performaction(UpdateSolrTesting.java:141)
    at UpdateSolrTesting.main(UpdateSolrTesting.java:101)
Caused by: org.apache.http.client.ClientProtocolException
    at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:867)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
    at org.apache.solr.client.solrj.impl.HttpSolrServer.request(HttpSolrServer.java:395)
    ... 7 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:660)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:486)
    at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863)
    ... 11 more

【问题讨论】:

    标签: java http solr solrj


    【解决方案1】:

    您需要的称为“抢先式身份验证”。这告诉 http 客户端在第一次调用 url 时进行身份验证。当使用基本身份验证时,默认行为是发送两个请求。当 http 调用中的实体不可重用时,这可能会失败,就像您的情况一样。

    幸运的是,solr 已经有一种内置方式,可以通过为 SolrHttpClientBuilder 使用不同的客户端构建工厂来启用抢先式身份验证。

    String userName = "someUserName";
    String password = "secretPassword";
    
    ModifiableSolrParams params = new ModifiableSolrParams();
    params.set(HttpClientUtil.PROP_BASIC_AUTH_USER, userName);
    params.set(HttpClientUtil.PROP_BASIC_AUTH_PASS, password);
    
    // set the params for authentication here
    PreemptiveBasicAuthClientBuilderFactory.setDefaultSolrParams(params);
    PreemptiveBasicAuthClientBuilderFactory preemptiveBasicAuthClientBuilderFactory = new PreemptiveBasicAuthClientBuilderFactory();
    
    // create a new client builder from the preemptive client builder factory
    SolrHttpClientBuilder httpClientBuilder = preemptiveBasicAuthClientBuilderFactory
                .getHttpClientBuilder(Optional.empty());
    
    // set the client builder to be used by the clientUtil 
    HttpClientUtil.setHttpClientBuilder(httpClientBuilder);
    
    // the params need to be passed here too
    CloseableHttpClient httpAuthClient = HttpClientUtil.createClient(params);
    
    // now build the solr client with the special http client
    Builder solrClientBuilder = new HttpSolrClient.Builder(solrClientConfig.getSolrUrl()).withHttpClient(httpAuthClient);
    
    // create solr client
    SolrClient client = solrClientBuilder.build();
    

    切记不要在请求级别设置授权参数,否则抢占式验证将不起作用。

    【讨论】:

    • 我认为这是根据solr文档Global (JVM) Basic Auth Credentials最相关的答案
    • 这是最好的答案:对官方文档中提到的根本原因和解决方案有正确的假设。有人可能认为这是相关的,例如POST 请求和它们是不可重复的(可能是这种情况),但实际上它是关于不可重复的“实体”(httpcore 级别的抽象):javadoc.io/doc/org.apache.httpcomponents/httpcore/4.4.4/org/…
    • 另外值得注意的是,如果您的应用程序中需要多个客户端,您应该使用官方文档中描述的系统属性,这样您就不需要过多地更改现有代码。
    【解决方案2】:

    这只是因为在执行 POST 或 DELETE 调用时没有发送身份验证参数,所以解决方案是你需要在你的 http 客户端中修复它

    我正在使用 solr 6.2.0 及其对应的 java 客户端

    所以我创建了一个新的 SolrHttp 客户端,如下所示

    public class TEHttpSolrClient extends HttpSolrClient {
    
    private static final String UTF_8 = StandardCharsets.UTF_8.name();
    
    public TEHttpSolrClient(String baseURL) {
        super(baseURL);
    }
    
    @Override
    public NamedList<Object> request(final SolrRequest request, String collection) throws SolrServerException, IOException {
        ResponseParser responseParser = request.getResponseParser();
        if (responseParser == null) {
            responseParser = parser;
        }
        return request(request, responseParser, collection);
    }
    
    public NamedList<Object> request(final SolrRequest request, final ResponseParser processor, String collection)
            throws SolrServerException, IOException {
        HttpRequestBase method = createMethod(request, collection);
        String userPass = "<username>:<password>";
        String encoded = Base64.byteArrayToBase64(userPass.getBytes(UTF_8));
        // below line will make sure that it sends authorization token every time in all your requests
        method.setHeader(new BasicHeader("Authorization", "Basic " + encoded));
        return executeMethod(method, processor);
    }
    
    }
    

    还要调用客户端,你应该像下面这样调用它

    private static SolrClient solr = new TEHttpSolrClient.Builder("<solr core url>").build();
    

    【讨论】:

      【解决方案3】:

      已经问过类似的问题,您可以查看以下链接以获得一些想法。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-06
      • 2018-11-02
      • 1970-01-01
      • 2014-01-24
      • 2017-11-27
      • 1970-01-01
      相关资源
      最近更新 更多