SolrCloud 7.2带BasicAuth时IndexFetcher请求未认证致401错误
在SolrCloud 7.2开启BasicAuth的场景下,使用IndexFetcher执行索引恢复或复制时出现401未授权错误,从你提供的日志可以看到明确的认证失败提示:
2018-01-25 13:16:22.538 WARN (indexFetcher-25-thread-1) [c:myCollection s:shard1 r:core_node3 x:myCollection_shard1_replica_t1] o.a.s.h.IndexFetcher Master at: http://server1:8983/solr/myCollection_shard1_replica_t4/ is not available. Index fetch failed by exception: org.apache.solr.client.solrj.impl.HttpSolrClient$RemoteSolrException: Error from server at http://server1:8983/solr/myCollection_shard1_replica_t4 : Expected mime type application/octet-stream but got text/html. Error 401 Unauthorized request, Response code: 401 HTTP ERROR 401 Problem accessing /solr/myCollection_shard1_replica_t4/replication. Reason: Unauthorized request, Response code: 401
问题根源
你已经排查到关键信息:IndexFetcher本应从initArgs中读取HTTP认证的用户名和密码,但即使在复制处理器的slave标签中配置了httpBasicAuthUser和httpBasicAuthPassword,这两个参数始终为null。这是因为Solr 7.2的复制模块在初始化IndexFetcher时,没有正确将这两个配置参数传递到initArgs中,导致IndexFetcher创建的HTTP客户端没有携带认证信息,最终触发401错误。
可行解决方案
1. 临时验证方案(硬编码源码)
如果你需要快速验证功能恢复,可以直接修改Solr源码中的IndexFetcher类,在创建HttpSolrClient的逻辑中硬编码认证信息:
// 找到IndexFetcher中初始化HttpSolrClient的代码段,添加以下内容 String authUsername = "你的用户名"; String authPassword = "你的密码"; if (authUsername != null && authPassword != null) { httpClient.setBasicAuthCredentials(authUsername, authPassword); }
重新编译Solr并替换对应的jar包后,索引恢复/复制功能会正常工作。不过这种方式不适合生产环境,因为无法灵活修改配置,且每次Solr版本升级都需要重新修改。
2. 根源修复方案(修正参数传递逻辑)
要彻底解决问题,需要调整Solr复制模块的参数传递逻辑:
- 定位到
ReplicationHandler类(负责解析复制配置的核心类),在初始化IndexFetcher的代码中,从slave配置里提取httpBasicAuthUser和httpBasicAuthPassword,并将这两个参数放入initArgs中 - 在IndexFetcher的构造方法或初始化逻辑中,从
initArgs中读取这两个参数,然后设置到HttpSolrClient的认证配置中
这种方式需要对Solr源码进行定制开发,适合有源码修改能力的团队,修复后可以正常通过配置文件管理认证信息。
3. 替代方案(URL嵌入认证信息)
如果暂时无法修改源码,可以在masterUrl中直接嵌入认证信息,让HTTP客户端自动携带认证参数:
<lst name="slave"> <str name="masterUrl">http://username:password@server1:port/solr/myCollection/replication</str> </lst>
注意:这种方式会将密码明文暴露在配置文件中,存在安全风险,建议仅在测试环境使用,生产环境务必结合HTTPS来降低密码泄露的风险。
内容的提问来源于stack exchange,提问作者Giannis

