原文:https://brandnewuser.iteye.com/blog/2318027
Solr的在5.0版本后,不再提供战争包部署的方式,取而代之的是内置了码头服务,
但是我们发现其中并没有内置任何安全性相关检查,任何人如果知道了我们的外网地址就能直接访问并修改其中的索引。经过查找可以使用码头的方式来限制网络访问。
Solr的/服务器/ Solr的-web应用/ WEB-INF / web.xml文件中增加以下字段:
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的/服务器的/ etc /的jetty.xml中增加呼叫标签:
XML代码
- < 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 >
- </ 新>
- </ Arg >
- </ Call >
配置中指定密码文件的路径,可以在其中使用<SystemProperty>来共同组合路径,例如配置了环境变量的情况下,可以使用下面的方式:
XML代码
- < Set name = “config” > < SystemProperty name = “jetty.home” default = “。” /> /etc/realm.properties </ Set >
而指定的realm.properties就是相关密码文件了:
XML代码
- 管理员:XXXX,solr_admin
设置完成,重新启动Solr的即可,如果不输入用户名和密码,无法登陆成功:
注意该方法同样会影响HttpSolr连接以及SolrCloud连接,报出下面的错误:
的Java代码
- { “code” :500 ,“codeMsg” :“来自服务器的错误:http:// xxx:8983 / solr / brand:预期的mime类型应用程序/八位字节流但是得到了text / html。<html> \ n <head> \ n <meta http-equiv = \“Content-Type \”content = \“text / html; charset = UTF-8 \“/> \ n <title>错误401未授权</ title> \ n </ head> \ n <body> <h2> HTTP错误401 </ h2> \ n <p>访问/的问题solr / brand / select。原因:\ n <pre>未经授权</ pre> </ p> <hr> <i> <small>由Jetty提供支持:// </ small> </ i> <hr /> \ n \ n </ body> \ n </ html> \ n“ }
我们可以使用简单验证的方式来测试一下:
的Java代码
- URL url = new URL(“http:// xxxx:8983 / solr /” );
- 字符串编码= Base64.encode(“admin:xxxx” .getBytes());
- HttpURLConnection connection =(HttpURLConnection)url.openConnection();
- connection.setRequestMethod(“GET” );
- connection.setDoOutput(true );
- connection.setRequestProperty(“授权” , “基本” +编码);
- InputStream content =(InputStream)connection.getInputStream();
- BufferedReader in =
- new BufferedReader(new InputStreamReader(content));
- 字符串行;
- while ((line = in.readLine())!= null ){
- 的System.out.println(线);
- }
如果加上凭证,是可以成功地将结果HTML打印出来,否则提示401(未授权)错误。
此时使用SolrCloud的情况下,就不能用CloudSolrClient中内置的HttpClient的,而只能在外部声明并传入,顺带建立CredentialsProvider,用于基本权限验证:
的Java代码
- 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)
- 。建立();
- 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);
此时就可以像以前一样正常查询了,注意在已经添加凭据情况下,如果此时服务器不需要验证,也不会出错。
对定时全/增量导入的影响
如果增加了安全校验,同样也会影响full-import,delta-import的执行,此时从solr.log日志中就可以拿到错误的信息:
的Java代码
- 2016 - 08 - 29 09 :10 :41.925 INFO(Timer- 0 )[] oashdsBaseTimerTask [product] <索引更新过程>过程开始于............... 29.08 。2016 09 :10 :41 925
- 2016 - 08 - 29 09 :10 :41.948 INFO(Timer- 0 )[] oashdsBaseTimerTask [product] <索引更新过程>完整URL http:// localhost:8983 / solr / product / dataimport?command = delta-import&clean = false&commit =真
- 2016 - 08 - 29 09 :10 :41.958 INFO(Timer- 0 )[] oashdsBaseTimerTask [product] <索引更新过程>响应消息未经授权
- 2016 - 08 - 29 09 :10 :41.958 INFO(Timer- 0 )[] oashdsBaseTimerTask [product] <索引更新过程>响应代码 401
- 2016 - 08 - 29 09 :10 :41.986 INFO(Timer- 0 )[] oashdsBaseTimerTask [product] <索引更新过程>与服务器localhost断开连接
- 2016 - 08 - 29 09 :10 :41.986 INFO(Timer- 0 )[] oashdsBaseTimerTask [product] <索引更新流程>流程于................ 29.08 结束 。2016 09 :10 :41 986
在全面导入/增量导入的相关代码中,没有涉及到权限验证部分,直接使用HTTP连接:
的Java代码
- protected void sendHttpPost(String completeUrl,String coreName){
- DateFormat df = new SimpleDateFormat(“dd.MM.yyyy HH:mm:ss SSS” );
- Date startTime = new Date();
- //准备核心变量
- String core = coreName == null ? “” : “[” + coreName + “]” ;
- logger.info(核心
- + “<索引更新过程>过程从..............开始。”
- + df.format(startTime));
- 尝试 {
- URL url = 新 网址(completeUrl);
- HttpURLConnection conn =(HttpURLConnection)url.openConnection();
- conn.setRequestMethod(“POST” );
- conn.setRequestProperty(“type” , “submit” );
- conn.setDoOutput(true );
- //发送HTTP POST
- conn.connect();
- logger.info(核心+ “<索引更新过程>完整URL \ t \ t \ t \ t \ t”
- + conn.getURL());
- logger.info(核心+ “<索引更新过程>响应消息\ t \ t \ t \ t”
- + conn.getResponseMessage());
- logger.info(核心+ “<索引更新过程>响应代码\ t \ t \ t”
- + conn.getResponseCode());
- //如果发生错误,请侦听属性文件中的更改
- if (conn.getResponseCode()!= 200 ){
- reloadParams();
- }
- conn.disconnect();
- logger.info(核心
- + “<索引更新过程>与服务器\ t \ t \ t断开连接”
- +服务器);
- Date endTime = new Date();
- logger.info(核心
- + “<索引更新过程>过程结束于................”
- + df.format(endTime));
- } catch (MalformedURLException mue){
- logger.error(“无法汇编HTTP POST的URL” ,mue);
- } catch (IOException ioe){
- logger.error(
- “尝试发送HTTP POST时无法连接到指定的URL” ,
- IOE);
- } catch (例外e){
- logger.error(“无法发送HTTP POST” ,e);
- }
- }
这种方式同样需要增加权限验证,在conn执行连接之前,要设置认证选项:
的Java代码
- String encoding = Base64.encode(“username:password”.getBytes());
- conn.setRequestProperty(“授权” , “基本” +编码);
注意当前使用的仅仅是硬编码设置的用户名,密码,修改完成后,要将原有的罐子包(Apache的solr的-dataimportscheduler-1.0.jar)进行重新编译并替换,重启solr的服务即可。
使用内置的HttpSolrClient
即并不传入原来的,还有另外一种方法,可用于配置基本用户以及密码认证,在HttpClientConfigurer类中对DefaultHttpClient的参数进行配置时,使用了下面的属性配置:
的Java代码
- final String basicAuthUser = config
- 获得(HttpClientUtil.PROP_BASIC_AUTH_USER);
- final String basicAuthPass = config
- 获得(HttpClientUtil.PROP_BASIC_AUTH_PASS);
如果使用这种方式,那么在创建内置的HttpSolrClient时需要传入参数,可以在PARAMS中加入基本认证即可。
的Java代码
- ModifiableSolrParams params = new ModifiableSolrParams();
- params.set(HttpClientUtil.PROP_MAX_CONNECTIONS, 128 );
- params.set(HttpClientUtil.PROP_MAX_CONNECTIONS_PER_HOST, 32 );
- params.set(HttpClientUtil.PROP_FOLLOW_REDIRECTS, false );
- params.set(HttpClientUtil.PROP_BASIC_AUTH_USER, “admin” );
- params.set(HttpClientUtil.PROP_BASIC_AUTH_PASS, “zhen.com” );
- params.set(HttpClientUtil.PROP_MAX_CONNECTIONS, 1000 );
- params.set(HttpClientUtil.PROP_ALLOW_COMPRESSION, true );
- params.set(HttpClientUtil.PROP_MAX_CONNECTIONS_PER_HOST, 1000 );
- CloseableHttpClient closeableHttpClient = HttpClientUtil.createClient(params);
- HttpSolrClient solrClient = new HttpSolrClient(solrurl,closeableHttpClient);
同样的方法也适用于CloudSolrClient。