Solr Identity authentication and authorization update exception solution
In the previous solr tutorial, permission verification is not enabled for solr, and authentication is not required for all operations. At that time, it was mentioned that if solr enabled permission verification, you can change solr’s host with the user name/password. However, the real situation is not quite the same. If the query is OK, the modification operation will be thrown exception
This article will take you to understand, what is this ghost animal phenomenon
I. Solr Configures user login
1. Install
In previous solr series tutorials, solr installed by Docker, the following steps are also directly for solr configuration in Docker, the basic steps are the same
For details, please refer to: [Search series] Solr environment construction and simple test
If you don’t want to see it, just use the following command:
docker pull solr
docker run --name my-solr -d -p 8983:8983 -t solr
Copy the code
2. The configuration
How to configure user login authentication for Solr8
To access the instance, use the root user; otherwise, some operations may not be authorized
docker exec -u root -it my-solr /bin/bash
Copy the code
Create an authentication file
vim server/etc/verify.properties
Copy the code
The content is in the following format: user name: password, permission, one account per row
root:123,admin
Copy the code
Configure the authentication file
vim server/contexts/solr-jetty-context.xml
Copy the code
Add the following to the Configure tag
<Get name="securityHandler">
<Set name="loginService">
<New class="org.eclipse.jetty.security.HashLoginService">
<Set name="name">Verify the name -</Set>
<Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/verify.properties</Set>
</New>
</Set>
</Get>
Copy the code
Modify the web. The XML
vim server/solr-webapp/webapp/WEB-INF/web.xml
Copy the code
Under the security-Constraint TAB, add
<login-config>
<auth-method>BASIC</auth-method>
<! -- Notice that the name is the same as the name in the Set tag -->
<realm-name>verify-name</realm-name>
</login-config>
Copy the code
Restart Solr for the configuration to take effect
docker restart my-solr
Copy the code
II. Scene replaying
Let’s talk about our environment
- Springboot: 2.2.1. RELEASE
- Solr: 8.0
1. Project environment
To build a simple Springboot project, XML depends on the following
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1. RELEASE</version>
<relativePath/> <! -- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>
<! -- Please note that when solr turns on login authentication, this dependency must have -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</pluginManagement>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
Copy the code
The corresponding configuration file application.yml
spring:
data:
solr:
Please note that the username and password are written directly in the URL
host: http://root:[email protected]:8983/solr
Copy the code
2. The repetition
If you have any questions about the basic operation of Solr, you can refer to my previous search series of blog posts to meet your literacy needs.
The core solr operation example is as follows:
@Data
public class DocDO implements Serializable {
private static final long serialVersionUID = 7245059137561820707L;
@Id
@Field("id")
private Integer id;
@Field("content_id")
private Integer contentId;
@Field("title")
private String title;
@Field("content")
private String content;
@Field("type")
private Integer type;
@Field("create_at")
private Long createAt;
@Field("publish_at")
private Long publishAt;
}
@Component
public class SolrOperater {
@Autowired
private SolrTemplate solrTemplate;
public void operate(a) {
testAddByDoc();
queryById();
}
public void testAddByDoc(a) {
SolrInputDocument document = new SolrInputDocument();
document.addField("id".999999);
document.addField("content_id".3);
document.addField("title"."testAddByDoc!");
document.addField("content"."Add da da da");
document.addField("type".2);
document.addField("create_at", System.currentTimeMillis() / 1000);
document.addField("publish_at", System.currentTimeMillis() / 1000);
UpdateResponse response = solrTemplate.saveDocument("yhh", document, Duration.ZERO);
solrTemplate.commit("yhh");
System.out.println("over:" + response);
}
private void queryById(a) {
DocDO ans = solrTemplate.getById("yhh".999999, DocDO.class).get();
System.out.println("queryById: "+ ans); }}Copy the code
SolrTemplat is defined as follows
@Configuration
public class SearchAutoConfig {
@Bean
@ConditionalOnMissingBean(SolrTemplate.class)
public SolrTemplate solrTemplate(SolrClient solrClient) {
return newSolrTemplate(solrClient); }}Copy the code
To begin testing
@SpringBootApplication
public class Application {
public Application(SolrOperater solrOperater) {
solrOperater.operate();
}
public static void main(String[] args) { SpringApplication.run(Application.class); }}Copy the code
Note that when the above scenario is replicated, the query is found to be fine, and modifications throw an exception
3. Solutions
A. version
When I used Solr before, it was the same as the above operation mode, but there was no such problem, which was a bit painful;
Find the previous project to check the version, found that the previous solr-Solrj used 6.6.5, try to change the version (the default version is 8.2.0)
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>6.6.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
</exclusion>
</exclusions>
</dependency>
Copy the code
Witness the miracle of the moment, the execution is normal, although the saveDocument method call red, but does not affect the specific execution oh
b. SystemDefaultHttpClient
Through a debugging, step by step, finally find out why 6.6.5 solr-Solrj works normally, but 8.2.0 doesn’t (if you want to know this boring process, please let me know in the comments, otherwise I don’t know when I can see 😂).
The key problem is that older versions use SystemDefaultHttpClient to implement solR communication; The new version uses InternalHttpClient
One possible solution is to specify Solr’s HttpClient instead of downgrading
In the configuration class, do the following:
@Bean
public HttpSolrClient solrClient(a) {
HttpClient httpClient = new SystemDefaultHttpClient();
return new HttpSolrClient.Builder(url).withHttpClient(httpClient).build();
}
Copy the code
Then test, also normal execution, output results do not screen shots, you can test yourself
C. HttpClient interceptor
Preemptive Basic Authentication with Apache HttpClient 4 Preemptive Basic authentication with Apache HttpClient 4
SystemDefaultHttpClient has a delete annotation, which means it is not recommended to use it directly, so we can use it to meet our needs, so we can do as follows
@Value("${spring.data.solr.host}")
private String url;
@Data
public static class UrlDo {
private String url;
private String user;
private String pwd;
private String host;
private int port;
public static UrlDo parse(String url) throws MalformedURLException {
/ / http://root:[email protected]:8983/solr
URL u = new URL(url);
UrlDo out = new UrlDo();
out.setHost(u.getHost());
out.setPort(u.getPort());
String userInfo = u.getUserInfo();
if(! StringUtils.isEmpty(userInfo)) { String[] users = org.apache.commons.lang3.StringUtils.split(userInfo,":");
out.setUser(users[0]);
out.setPwd(users[1]);
}
out.setUrl(url);
returnout; }}public class SolrAuthInterceptor implements HttpRequestInterceptor {
@Override
public void process(final HttpRequest request, final HttpContext context) {
AuthState authState = (AuthState) context.getAttribute(HttpClientContext.TARGET_AUTH_STATE);
if (authState.getAuthScheme() == null) {
CredentialsProvider credsProvider =
(CredentialsProvider) context.getAttribute(HttpClientContext.CREDS_PROVIDER);
HttpHost targetHost = (HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());
Credentials creds = credsProvider.getCredentials(authScope);
authState.update(newBasicScheme(), creds); }}}@Bean
public HttpSolrClient solrClient(a) throws MalformedURLException {
UrlDo urlDo = UrlDo.parse(url);
CredentialsProvider provider = new BasicCredentialsProvider();
provider.setCredentials(new AuthScope(urlDo.getHost(), urlDo.getPort()),
new UsernamePasswordCredentials(urlDo.getUser(), urlDo.getPwd()));
HttpClientBuilder builder = HttpClientBuilder.create();
// Notice the following line, specifying the interceptor, which is used to set authentication information
builder.addInterceptorFirst(new SolrAuthInterceptor());
builder.setDefaultCredentialsProvider(provider);
CloseableHttpClient httpClient = builder.build();
return new HttpSolrClient.Builder(url).withHttpClient(httpClient).build();
}
Copy the code
The above implementation is a bit long, so let’s break it down
UrlDo
Parse solr’s URL to get what we needhost + port + user + password
solrClient
: in creatingSolrClient
Bean instance, specify the appropriate authorization informationSolrAuthInterceptor
: Custom interceptor, updatedauthState
information
d. SolrRequest
The above three methods are applicable to solr using SolrClient or SolrTemplate. Of course, I can discard them completely and use SolrRequest directly, as follows
SolrInputDocument document = new SolrInputDocument();
document.addField("id".999999);
document.addField("content_id".3);
document.addField("title"."testAddByDoc!");
document.addField("content"."Add da da da");
document.addField("type".2);
document.addField("create_at", System.currentTimeMillis() / 1000);
document.addField("publish_at", System.currentTimeMillis() / 1000);
UpdateRequest updateRequest = new UpdateRequest();
updateRequest.setBasicAuthCredentials("root"."123");
updateRequest.add(document);
UpdateResponse response = updateRequest.process(solrClient, "yhh");
updateRequest.commit(solrClient, "yhh");
Copy the code
4. Summary
This post focuses on four solutions for solr update exceptions that require login authentication
- drop
solr-solrj
Version to6.6.0
- The specified
SolrClient
theHttpClient
forSystemDefaultHttpClient
- HttpClient interceptor
- SolrRequest Specifies the user name and password
The solution is given above, but why is this a problem?
Directly test the solr update operation by using curl. It returned normally and there was no problem. Then what is the cause of this problem and whose pot is it
II. The other
Series of blog posts & project source code
Refer to the post
- Configure user login authentication for SolR8
- Preemptive Basic authentication with Apache HttpClient 4
Series of blog posts
- 200115-SpringBoot series Solr query using posture summary
- 200114-SpringBoot series tutorial Solr documentation removed
- 190526-SpringBoot Advanced Search for Solr documentation added and modified using posture
- 190510-SpringBoot Advanced Search Solr environment setup and simple test
Engineering source
- Project: github.com/liuyueyi/sp…
- Source: github.com/liuyueyi/sp…
1. An ashy Blog
As far as the letter is not as good, the above content is purely one’s opinion, due to the limited personal ability, it is inevitable that there are omissions and mistakes, if you find bugs or have better suggestions, welcome criticism and correction, don’t hesitate to appreciate
Below a gray personal blog, record all the study and work of the blog, welcome everyone to go to stroll
- A grey Blog Personal Blog blog.hhui.top
- A Grey Blog-Spring feature Blog Spring.hhui.top