[收藏] solr 5.5 设置访问密码



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

 
 
注意该方法同样会影响HttpSolr连接以及SolrCloud连接,报出下面的错误:
 
 
Java代码   收藏代码
  1. {"code":500,"codeMsg":"Error from server at http://xxx: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"}  
 
 
我们可以使用简单验证的方式来测试一下:
 
 
Java代码   收藏代码
  1. URL url = new URL("http://xxxx:8983/solr/");  
  2. String encoding = Base64.encode("admin:xxxx".getBytes());  
  3.    
  4. HttpURLConnection connection = (HttpURLConnection) url.openConnection();  
  5. connection.setRequestMethod("GET");  
  6. connection.setDoOutput(true);  
  7. connection.setRequestProperty  ("Authorization""Basic " + encoding);  
  8. InputStream content = (InputStream)connection.getInputStream();  
  9. BufferedReader in  =  
  10.         new BufferedReader (new InputStreamReader(content));  
  11. String line;  
  12. while ((line = in.readLine()) != null) {  
  13.     System.out.println(line);  
  14. }  
  
如果加上credentials,是可以成功地将结果html打印出来,否则提示401(Unauthorized)错误。
 
此时使用SolrCloud的情况下,就不能用CloudSolrClient中内置的httpClient,而只能在外部声明并传入,顺带建立CredentialsProvider,用于Basic权限验证:
 
 
Java代码   收藏代码
  1. String zkHost = PropertiesUtil.getProperty("zkhost", PROPERTY_FILE_NAME);  
  2. String collection = PropertiesUtil.getProperty(collectionName.getConfigName(), PROPERTY_FILE_NAME);  
  3. int zkClientTimeout = StringUtils  
  4.       .parseInt(PropertiesUtil.getProperty("zkClientTimeout", PROPERTY_FILE_NAME));  
  5. int zkConnectTimeout = StringUtils  
  6.       .parseInt(PropertiesUtil.getProperty("zkConnectTimeout", PROPERTY_FILE_NAME));  
  7.    
  8.         PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();  
  9.         // 连接池最大连接数  
  10.         connManager.setMaxTotal(50);  
  11.         // 每个路由最大连接数  
  12.         connManager.setDefaultMaxPerRoute(20);  
  13.    
  14.         // http请求配置信息  
  15.         RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(2000).setSocketTimeout(2000)  
  16.                 .setConnectionRequestTimeout(500).setCookieSpec(CookieSpecs.STANDARD)  
  17.                 .build();  
  18.    
  19.         CredentialsProvider credentialsProvider = new BasicCredentialsProvider();  
  20.         credentialsProvider.setCredentials(new AuthScope(PropertiesUtil.getProperty("solrHost", PROPERTY_FILE_NAME),  
  21.                 Integer.parseInt(PropertiesUtil.getProperty("solrPort", PROPERTY_FILE_NAME))),  
  22.                 new UsernamePasswordCredentials(PropertiesUtil.getProperty("solrUserName", PROPERTY_FILE_NAME),  
  23.                         PropertiesUtil.getProperty("solrPassword", PROPERTY_FILE_NAME)));  
  24.    
  25.         CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connManager).setDefaultRequestConfig(requestConfig)  
  26.                 .setConnectionManagerShared(true).setDefaultCredentialsProvider(credentialsProvider).build();  
  27.    
  28.         CloudSolrClient cloudSolrClient = new CloudSolrClient(zkHost, httpClient);  
 
 
此时就可以像以前一样正常查询了,注意在已经添加Credentials情况下,如果此时服务器不需要验证,也不会出错。 
 
对定时full/delta-import的影响
 
如果增加了安全校验,同样也会影响full-import, delta-import的执行,此时从solr.log日志中就可以拿到错误的信息:
 
Java代码   收藏代码
  1. 2016-08-29 09:10:41.925 INFO  (Timer-0) [   ] o.a.s.h.d.s.BaseTimerTask [product] <index update process> Process started at .............. 29.08.2016 09:10:41 925  
  2. 2016-08-29 09:10:41.948 INFO  (Timer-0) [   ] o.a.s.h.d.s.BaseTimerTask [product] <index update process> Full URL                      http://localhost:8983/solr/product/dataimport?command=delta-import&clean=false&commit=true  
  3. 2016-08-29 09:10:41.958 INFO  (Timer-0) [   ] o.a.s.h.d.s.BaseTimerTask [product] <index update process> Response message                  Unauthorized  
  4. 2016-08-29 09:10:41.958 INFO  (Timer-0) [   ] o.a.s.h.d.s.BaseTimerTask [product] <index update process> Response code             401  
  5. 2016-08-29 09:10:41.986 INFO  (Timer-0) [   ] o.a.s.h.d.s.BaseTimerTask [product] <index update process> Disconnected from server              localhost  
  6. 2016-08-29 09:10:41.986 INFO  (Timer-0) [   ] o.a.s.h.d.s.BaseTimerTask [product] <index update process> Process ended at ................ 29.08.2016 09:10:41 986  
 
 
在full-import/delta-import的相关代码中,没有涉及到权限验证部分,直接使用http连接:
 
Java代码   收藏代码
  1. protected void sendHttpPost(String completeUrl, String coreName) {  
  2.   DateFormat df = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss SSS");  
  3.   Date startTime = new Date();  
  4.    
  5.   // prepare the core var  
  6.   String core = coreName == null ? "" : "[" + coreName + "] ";  
  7.    
  8.   logger.info(core  
  9.         + "<index update process> Process started at .............. "  
  10.         + df.format(startTime));  
  11.    
  12.   try {  
  13.    
  14.       URL url = new URL(completeUrl);  
  15.       HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  16.    
  17.       conn.setRequestMethod("POST");  
  18.       conn.setRequestProperty("type""submit");  
  19.       conn.setDoOutput(true);  
  20.    
  21.       // Send HTTP POST  
  22.       conn.connect();  
  23.    
  24.       logger.info(core + "<index update process> Full URL\t\t\t\t"  
  25.             + conn.getURL());  
  26.       logger.info(core + "<index update process> Response message\t\t\t"  
  27.             + conn.getResponseMessage());  
  28.       logger.info(core + "<index update process> Response code\t\t\t"  
  29.             + conn.getResponseCode());  
  30.    
  31.       // listen for change in properties file if an error occurs  
  32.       if (conn.getResponseCode() != 200) {  
  33.         reloadParams();  
  34.       }  
  35.    
  36.       conn.disconnect();  
  37.       logger.info(core  
  38.             + "<index update process> Disconnected from server\t\t"  
  39.             + server);  
  40.       Date endTime = new Date();  
  41.       logger.info(core  
  42.             + "<index update process> Process ended at ................ "  
  43.             + df.format(endTime));  
  44.   } catch (MalformedURLException mue) {  
  45.       logger.error("Failed to assemble URL for HTTP POST", mue);  
  46.   } catch (IOException ioe) {  
  47.       logger.error(  
  48.             "Failed to connect to the specified URL while trying to send HTTP POST",  
  49.             ioe);  
  50.   } catch (Exception e) {  
  51.       logger.error("Failed to send HTTP POST", e);  
  52.   }  
  53. }  
 
 
这种方式同样需要增加权限验证, 在conn执行连接之前,要设置认证选项:
 
Java代码   收藏代码
  1. String encoding = Base64.encode(“username:password".getBytes());  
  2. conn.setRequestProperty("Authorization""Basic " + encoding);  
 
 
注意当前使用的仅仅是硬编码设置的用户名、密码,修改完成后,要将原有的jar包(apache-solr-dataimportscheduler-1.0.jar)进行重新编译并替换,重启solr服务即可。
 

使用内置的HttpSolrClient
 
即并不传入原来的,还有另外一种方法,可用于配置基本用户以及密码认证,在HttpClientConfigurer类中对DefaultHttpClient的参数进行配置时,使用了下面的属性配置:
 
Java代码   收藏代码
  1. final String basicAuthUser = config  
  2.     .get(HttpClientUtil.PROP_BASIC_AUTH_USER);  
  3. final String basicAuthPass = config  
  4.     .get(HttpClientUtil.PROP_BASIC_AUTH_PASS);  
 
 
如果使用这种方式,那么在创建内置的HttpSolrClient时需要传入params,在params中加入基本认证即可。
 
Java代码   收藏代码
  1. ModifiableSolrParams params = new ModifiableSolrParams();  
  2.       params.set(HttpClientUtil.PROP_MAX_CONNECTIONS, 128);  
  3.       params.set(HttpClientUtil.PROP_MAX_CONNECTIONS_PER_HOST, 32);  
  4.       params.set(HttpClientUtil.PROP_FOLLOW_REDIRECTS, false);  
  5.       params.set(HttpClientUtil.PROP_BASIC_AUTH_USER, "admin");  
  6.       params.set(HttpClientUtil.PROP_BASIC_AUTH_PASS, "zhen.com");  
  7.       params.set(HttpClientUtil.PROP_MAX_CONNECTIONS, 1000);  
  8.       params.set(HttpClientUtil.PROP_ALLOW_COMPRESSION, true);  
  9.       params.set(HttpClientUtil.PROP_MAX_CONNECTIONS_PER_HOST, 1000);  
  10.       CloseableHttpClient closeableHttpClient = HttpClientUtil.createClient(params);  
  11.    
  12. HttpSolrClient solrClient = new HttpSolrClient(solrurl, closeableHttpClient);  
  
同样的方法也适用于CloudSolrClient。

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

 
 
注意该方法同样会影响HttpSolr连接以及SolrCloud连接,报出下面的错误:
 
 
Java代码   收藏代码
  1. {"code":500,"codeMsg":"Error from server at http://xxx: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"}  
 
 
我们可以使用简单验证的方式来测试一下:
 
 
Java代码   收藏代码
  1. URL url = new URL("http://xxxx:8983/solr/");  
  2. String encoding = Base64.encode("admin:xxxx".getBytes());  
  3.    
  4. HttpURLConnection connection = (HttpURLConnection) url.openConnection();  
  5. connection.setRequestMethod("GET");  
  6. connection.setDoOutput(true);  
  7. connection.setRequestProperty  ("Authorization""Basic " + encoding);  
  8. InputStream content = (InputStream)connection.getInputStream();  
  9. BufferedReader in  =  
  10.         new BufferedReader (new InputStreamReader(content));  
  11. String line;  
  12. while ((line = in.readLine()) != null) {  
  13.     System.out.println(line);  
  14. }  
  
如果加上credentials,是可以成功地将结果html打印出来,否则提示401(Unauthorized)错误。
 
此时使用SolrCloud的情况下,就不能用CloudSolrClient中内置的httpClient,而只能在外部声明并传入,顺带建立CredentialsProvider,用于Basic权限验证:
 
 
Java代码   收藏代码
  1. String zkHost = PropertiesUtil.getProperty("zkhost", PROPERTY_FILE_NAME);  
  2. String collection = PropertiesUtil.getProperty(collectionName.getConfigName(), PROPERTY_FILE_NAME);  
  3. int zkClientTimeout = StringUtils  
  4.       .parseInt(PropertiesUtil.getProperty("zkClientTimeout", PROPERTY_FILE_NAME));  
  5. int zkConnectTimeout = StringUtils  
  6.       .parseInt(PropertiesUtil.getProperty("zkConnectTimeout", PROPERTY_FILE_NAME));  
  7.    
  8.         PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();  
  9.         // 连接池最大连接数  
  10.         connManager.setMaxTotal(50);  
  11.         // 每个路由最大连接数  
  12.         connManager.setDefaultMaxPerRoute(20);  
  13.    
  14.         // http请求配置信息  
  15.         RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(2000).setSocketTimeout(2000)  
  16.                 .setConnectionRequestTimeout(500).setCookieSpec(CookieSpecs.STANDARD)  
  17.                 .build();  
  18.    
  19.         CredentialsProvider credentialsProvider = new BasicCredentialsProvider();  
  20.         credentialsProvider.setCredentials(new AuthScope(PropertiesUtil.getProperty("solrHost", PROPERTY_FILE_NAME),  
  21.                 Integer.parseInt(PropertiesUtil.getProperty("solrPort", PROPERTY_FILE_NAME))),  
  22.                 new UsernamePasswordCredentials(PropertiesUtil.getProperty("solrUserName", PROPERTY_FILE_NAME),  
  23.                         PropertiesUtil.getProperty("solrPassword", PROPERTY_FILE_NAME)));  
  24.    
  25.         CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connManager).setDefaultRequestConfig(requestConfig)  
  26.                 .setConnectionManagerShared(true).setDefaultCredentialsProvider(credentialsProvider).build();  
  27.    
  28.         CloudSolrClient cloudSolrClient = new CloudSolrClient(zkHost, httpClient);  
 
 
此时就可以像以前一样正常查询了,注意在已经添加Credentials情况下,如果此时服务器不需要验证,也不会出错。 
 
对定时full/delta-import的影响
 
如果增加了安全校验,同样也会影响full-import, delta-import的执行,此时从solr.log日志中就可以拿到错误的信息:
 
Java代码   收藏代码
  1. 2016-08-29 09:10:41.925 INFO  (Timer-0) [   ] o.a.s.h.d.s.BaseTimerTask [product] <index update process> Process started at .............. 29.08.2016 09:10:41 925  
  2. 2016-08-29 09:10:41.948 INFO  (Timer-0) [   ] o.a.s.h.d.s.BaseTimerTask [product] <index update process> Full URL                      http://localhost:8983/solr/product/dataimport?command=delta-import&clean=false&commit=true  
  3. 2016-08-29 09:10:41.958 INFO  (Timer-0) [   ] o.a.s.h.d.s.BaseTimerTask [product] <index update process> Response message                  Unauthorized  
  4. 2016-08-29 09:10:41.958 INFO  (Timer-0) [   ] o.a.s.h.d.s.BaseTimerTask [product] <index update process> Response code             401  
  5. 2016-08-29 09:10:41.986 INFO  (Timer-0) [   ] o.a.s.h.d.s.BaseTimerTask [product] <index update process> Disconnected from server              localhost  
  6. 2016-08-29 09:10:41.986 INFO  (Timer-0) [   ] o.a.s.h.d.s.BaseTimerTask [product] <index update process> Process ended at ................ 29.08.2016 09:10:41 986  
 
 
在full-import/delta-import的相关代码中,没有涉及到权限验证部分,直接使用http连接:
 
Java代码   收藏代码
  1. protected void sendHttpPost(String completeUrl, String coreName) {  
  2.   DateFormat df = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss SSS");  
  3.   Date startTime = new Date();  
  4.    
  5.   // prepare the core var  
  6.   String core = coreName == null ? "" : "[" + coreName + "] ";  
  7.    
  8.   logger.info(core  
  9.         + "<index update process> Process started at .............. "  
  10.         + df.format(startTime));  
  11.    
  12.   try {  
  13.    
  14.       URL url = new URL(completeUrl);  
  15.       HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  16.    
  17.       conn.setRequestMethod("POST");  
  18.       conn.setRequestProperty("type""submit");  
  19.       conn.setDoOutput(true);  
  20.    
  21.       // Send HTTP POST  
  22.       conn.connect();  
  23.    
  24.       logger.info(core + "<index update process> Full URL\t\t\t\t"  
  25.             + conn.getURL());  
  26.       logger.info(core + "<index update process> Response message\t\t\t"  
  27.             + conn.getResponseMessage());  
  28.       logger.info(core + "<index update process> Response code\t\t\t"  
  29.             + conn.getResponseCode());  
  30.    
  31.       // listen for change in properties file if an error occurs  
  32.       if (conn.getResponseCode() != 200) {  
  33.         reloadParams();  
  34.       }  
  35.    
  36.       conn.disconnect();  
  37.       logger.info(core  
  38.             + "<index update process> Disconnected from server\t\t"  
  39.             + server);  
  40.       Date endTime = new Date();  
  41.       logger.info(core  
  42.             + "<index update process> Process ended at ................ "  
  43.             + df.format(endTime));  
  44.   } catch (MalformedURLException mue) {  
  45.       logger.error("Failed to assemble URL for HTTP POST", mue);  
  46.   } catch (IOException ioe) {  
  47.       logger.error(  
  48.             "Failed to connect to the specified URL while trying to send HTTP POST",  
  49.             ioe);  
  50.   } catch (Exception e) {  
  51.       logger.error("Failed to send HTTP POST", e);  
  52.   }  
  53. }  
 
 
这种方式同样需要增加权限验证, 在conn执行连接之前,要设置认证选项:
 
Java代码   收藏代码
  1. String encoding = Base64.encode(“username:password".getBytes());  
  2. conn.setRequestProperty("Authorization""Basic " + encoding);  
 
 
注意当前使用的仅仅是硬编码设置的用户名、密码,修改完成后,要将原有的jar包(apache-solr-dataimportscheduler-1.0.jar)进行重新编译并替换,重启solr服务即可。
 

使用内置的HttpSolrClient
 
即并不传入原来的,还有另外一种方法,可用于配置基本用户以及密码认证,在HttpClientConfigurer类中对DefaultHttpClient的参数进行配置时,使用了下面的属性配置:
 
Java代码   收藏代码
  1. final String basicAuthUser = config  
  2.     .get(HttpClientUtil.PROP_BASIC_AUTH_USER);  
  3. final String basicAuthPass = config  
  4.     .get(HttpClientUtil.PROP_BASIC_AUTH_PASS);  
 
 
如果使用这种方式,那么在创建内置的HttpSolrClient时需要传入params,在params中加入基本认证即可。
 
Java代码   收藏代码
  1. ModifiableSolrParams params = new ModifiableSolrParams();  
  2.       params.set(HttpClientUtil.PROP_MAX_CONNECTIONS, 128);  
  3.       params.set(HttpClientUtil.PROP_MAX_CONNECTIONS_PER_HOST, 32);  
  4.       params.set(HttpClientUtil.PROP_FOLLOW_REDIRECTS, false);  
  5.       params.set(HttpClientUtil.PROP_BASIC_AUTH_USER, "admin");  
  6.       params.set(HttpClientUtil.PROP_BASIC_AUTH_PASS, "zhen.com");  
  7.       params.set(HttpClientUtil.PROP_MAX_CONNECTIONS, 1000);  
  8.       params.set(HttpClientUtil.PROP_ALLOW_COMPRESSION, true);  
  9.       params.set(HttpClientUtil.PROP_MAX_CONNECTIONS_PER_HOST, 1000);  
  10.       CloseableHttpClient closeableHttpClient = HttpClientUtil.createClient(params);  
  11.    
  12. HttpSolrClient solrClient = new HttpSolrClient(solrurl, closeableHttpClient);  
  
同样的方法也适用于CloudSolrClient。

原文链接: http://brandnewuser.iteye.com/blog/2318027
相关文章
相关标签/搜索