Solr Web增加Basic安全性验证

 
Solr在5.0版本后,不再提供war包部署的方式,取而代之的是内置了jetty服务,
 
但是我们发现其中并没有内置任何安全性相关检查,任何人如果知道了我们的外网地址就能直接访问并修改其中的索引。经过查找可以使用jetty的方式来限制web访问。
 
solr/server/solr-webapp/WEB-INF/web.xml中增加以下字段:
 
 
<security-constraint>
    <web-resource-collection>
      <web-resource-name>solr</web-resource-name>
      <url-pattern>/</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>solr_admin</role-name>
      <role-name>admin</role-name>
    </auth-constraint>
 
    <login-config>
      <auth-method>BASIC</auth-method>
      <realm-name>Solr Admin</realm-name>
    </login-config>
  </security-constraint>
 
 
配置验证方式BASIC(用户名密码的方式)。
 
solr/server/etc/jetty.xml中增加Call标签:
 
<Call name="addBean">
      <Arg>
        <New class="org.eclipse.jetty.security.HashLoginService">
          <Set name="name">Solr Admin</Set>
          <Set name="config">
            /Users/mazhiqiang/develop/tools/solr-5.5.0/server/etc/realm.properties
          </Set>
          <Set name="refreshInterval">0</Set>
        </New>
      </Arg>
    </Call>
 
 
config中指定密码文件的路径,可以在其中使用<SystemProperty>来共同组合路径,例如配置了环境变量的情况下,可以使用下面的方式:
 
 
<Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</Set>
  
而指定的realm.properties就是相关密码文件了:
 
admin:xxxx,solr_admin
 
 
设置完成,重新启动solr即可,如果不输入用户名和密码,无法登陆成功:
 
 

 
 
注意该方法同样会影响HttpSolr连接以及SolrCloud连接,报出下面的错误:
 
 
{"code":500,"codeMsg":"Error from server at http://119.254.106.213:8983/solr/brand: Expected mime type application/octet-stream but got text/html. <html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/>\n<title>Error 401 Unauthorized</title>\n</head>\n<body><h2>HTTP ERROR 401</h2>\n<p>Problem accessing /solr/brand/select. Reason:\n<pre>    Unauthorized</pre></p><hr><i><small>Powered by Jetty://</small></i><hr/>\n\n</body>\n</html>\n"}
 
 
我们可以使用简单验证的方式来测试一下:
 
 
URL url = new URL("http://xxxx:8983/solr/");
String encoding = Base64.encode("admin:xxxx".getBytes());
 
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setRequestProperty  ("Authorization", "Basic " + encoding);
InputStream content = (InputStream)connection.getInputStream();
BufferedReader in  =
        new BufferedReader (new InputStreamReader(content));
String line;
while ((line = in.readLine()) != null) {
    System.out.println(line);
}
  
如果加上credentials,是可以成功地将结果html打印出来,否则提示401(Unauthorized)错误。
 
此时使用SolrCloud的情况下,就不能用CloudSolrClient中内置的httpClient,而只能在外部声明并传入,顺带建立CredentialsProvider,用于Basic权限验证:
 
 
String zkHost = PropertiesUtil.getProperty("zkhost", PROPERTY_FILE_NAME);
String collection = PropertiesUtil.getProperty(collectionName.getConfigName(), PROPERTY_FILE_NAME);
int zkClientTimeout = StringUtils
      .parseInt(PropertiesUtil.getProperty("zkClientTimeout", PROPERTY_FILE_NAME));
int zkConnectTimeout = StringUtils
      .parseInt(PropertiesUtil.getProperty("zkConnectTimeout", PROPERTY_FILE_NAME));
 
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
        // 连接池最大连接数
        connManager.setMaxTotal(50);
        // 每个路由最大连接数
        connManager.setDefaultMaxPerRoute(20);
 
        // http请求配置信息
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(2000).setSocketTimeout(2000)
                .setConnectionRequestTimeout(500).setCookieSpec(CookieSpecs.STANDARD)
                .build();
 
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(new AuthScope(PropertiesUtil.getProperty("solrHost", PROPERTY_FILE_NAME),
                Integer.parseInt(PropertiesUtil.getProperty("solrPort", PROPERTY_FILE_NAME))),
                new UsernamePasswordCredentials(PropertiesUtil.getProperty("solrUserName", PROPERTY_FILE_NAME),
                        PropertiesUtil.getProperty("solrPassword", PROPERTY_FILE_NAME)));
 
        CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connManager).setDefaultRequestConfig(requestConfig)
                .setConnectionManagerShared(true).setDefaultCredentialsProvider(credentialsProvider).build();
 
        CloudSolrClient cloudSolrClient = new CloudSolrClient(zkHost, httpClient);
 
 
此时就可以像以前一样正常查询了,注意在已经添加Credentials情况下,如果此时服务器不需要验证,也不会出错。 
posted @ 2016-08-20 10:49  clamaa  阅读(977)  评论(0编辑  收藏  举报