This is the 16th day of my participation in Gwen Challenge


Eureka is a service discovery framework developed by Netflix. As a REST-based service, Eureka is mainly used to locate middle-tier services running in AWS domains for load balancing and middle-tier service failover. SpringCloud integrates it into its sub-project spring-Cloud-Netflix to implement SpringCloud’s service discovery capabilities.

Eureka consists of two components: Eureka Server and Eureka Client. How to deploy the specific here not to say, directly to the problem

When registering the Eureka client, you need to configure the server address

eureka:
  instance:
    hostname: hello-service
    prefer-ip-address: true
    instance-id: ${eureka.instance.hostname}:${server.port}
  client:
    register-with-eureka: true 
    fetch-registry: true
    service-url: 
    	defaultZone: "http://localhost:8761/eureka/" 
Copy the code

After this configuration, the client will register with the Eureka registry and you can see in the Eureka interface:

But this interface exposed to the outside, will leak the registration information, the general company is not allowed to expose the background interface without security certification

So try to encrypt the Eureka interface

The introduction of the security

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
Copy the code

Add basic authentication to Eureka server:

spring:
  application:
    name: eureka-server 
  security: 
    basic:
      enabled: true
    user:
      name: admin
      password: 123456
Copy the code

After the configuration, you need a user name and password to access the Eureka interface

However, when I log in, I find that the hello service is not registered

Yihoo, it must be the reason that the authentication information is not configured on the client. The authentication configuration mode of the client is found on the official website

Cloud. Spring. IO/spring – clou…

Modify the hello service configuration as follows:

eureka:
  instance:
    hostname: hello-service
    prefer-ip-address: true
    instance-id: ${eureka.instance.hostname}:${server.port}
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://admin:123456@localhost:8761/eureka/
Copy the code

The hello service is still not registered successfully. After adding basic authentication, it does not support cross-domain access.

So, quickly add configurations to remove cross-domain interception

@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
     // http.csrf().disable(); // In one way, CSRF is directly disabled, and in the other way, THE URL is configured
        http.csrf().ignoringAntMatchers("/eureka/**");
        super.configure(http); }}Copy the code

The password is not allowed to appear in the configuration or code, so what should I do?

The first thing that comes to mind is password encryption, so find PasswordEncoderFactories in Spring-Securiry

PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("123456")
Copy the code

Then put the encrypted result into the Eureka server configuration file:

security: 
  basic:
    enabled: true 
  user:
    name: admin
    password: '{bcrypt} $2 a $10 $mhH7ogkRB91YDUO3F883JugDMHz2o6miT95. 8 ukqec6ed4z2xyhmm' // Must have quotation marks
Copy the code

What about the Eureka client? It’s the same thing

client:
  register-with-eureka: true
  fetch-registry: true
  service-url:
    defaultZone: http:/ / admin: {bcrypt} $2 a $10 $mhH7ogkRB91YDUO3F883JugDMHz2o6miT95. 8 ukqec6ed4z2xyhmm @ localhost: 8761 / eureka
Copy the code

However, eureka does not decrypt when it is registered

Failed to resolve the Eureka server address, even in quotes

If the Eureka client registers the message, the server does not decrypt it.

As you can see from the figure above, more complex requirements need to be implemented by injecting clientFilter, so

@Configuration
@Priority(Integer.MIN_VALUE)
public class UserCilentFilter extends ClientFilter {
    @Override
    public ClientResponse handle(ClientRequest clientRequest) throws ClientHandlerException {
        try {
            String originUrl = clientRequest.getURI().toString();
            if(originUrl.contains("@")) {return this.getNext().handle(clientRequest);
            }
            String userNameAndPwd = "http://admin"+ jiemi("' {bcrypt} $2 a $10 $mhH7ogkRB91YDUO3F883JugDMHz2o6miT95. 8 ukqec6ed4z2xyhmm '");
            String addUserInfoUrl = originUrl.replaceFirst("http://", userNameAndPwd);
            clientRequest.setURI(new URI(addUserInfoUrl));
        } catch (URISyntaxException e) {
            // FIXME: 2021/4/2
        }
        return this.getNext().handle(clientRequest);
    }

    private String jiemi(String pwd) {
        // FIXME:decryption
        return pwd;
    }


    @Bean
    public DiscoveryClient.DiscoveryClientOptionalArgs discoveryClientOptionalArgs(a) {
        DiscoveryClient.DiscoveryClientOptionalArgs discoveryClientOptionalArgs = new DiscoveryClient.DiscoveryClientOptionalArgs();
        discoveryClientOptionalArgs.setAdditionalFilters(Collections.singletonList(new UserCilentFilter()));
        returndiscoveryClientOptionalArgs; }}Copy the code

The idea is to have other clients register without the username and password, and then add the basic authenticated username and password to the custom filter if there is no username and password

When the service is registered, it will be blocked by other security filters and fail to access the custom interceptor, even though @priority (integer.min_value) has the highest Priority

Is it possible to intercept further forward? Is it possible to add a ServletRequest interceptor?

@Configuration
public class ServerRequestAuthFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        // Business implementation, according to the requested IP or parameters to determine whether the registration or access can be performed
// String addUserInfoUrl = originUrl.replaceFirst("http://", "http://admin:123456@");filterChain.doFilter(request, response); }}Copy the code

However, if this modification is made, the login web interface will also go to the interceptor, which will also add authentication

In other words, authentication can be added directly without distinguishing between other clients registering or accessing from the interface

There is no better way to do this than to simply drop the eureka registration in the security interceptor

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().antMatchers("/eureka/**").permitAll();
    super.configure(http);
}
Copy the code

After this setting, authentication is not required for eureka-related registration and query, except for directly accessed interfaces

Now that we’ve done layered authentication, let’s see if there’s another way to achieve the same goal

eureka:
  dashboard:
    enabled: false
Copy the code

After setting up the script at startup, the effect is similar and cannot be accessed on the eureka main screen

All the operations above are for the sake of information security. Another component that is often forgotten to be considered is Spring Boot Actuator. For the endpoint provided by Spring Boot Actuator, the following measures can be taken to reduce the risk of security attacks as much as possible

  1. Minimum granularity exposes the endpoint. Only show really open and use the endpoint, instead of configuration: management endpoints. Web. Exposure. Include = *.
  2. Configure an independent access port for the endpoint, which is separated from the port of the Web service. In this way, the endpoint of the actuator is not exposed when the Web service is exposed. Example: the management port = 8099.
  3. The spring-boot-starter-Security dependency is introduced and access control is configured for the endpoint of the actuator.
  4. Evaluate carefully whether to use spring-boot-Stater -actuator. According to my personal experience, so far I have not met any requirements that require the introduction of Spring-boot-Stater -actuator to solve the problem. If you do not understand the security risks described above, I suggest you remove the dependence first.

Information security has become a problem that major companies have to consider, so precise permission control is also essential, I hope this article can inspire you to use SpringCloud related components security control.

If you think I can write, remember to like, one key three even don’t mind.

☞ Every week, like the fairies, after reading the like, get into the habit of a natural