【问题标题】:How avoid the certificate validation in spring-boot-admin?如何避免 spring-boot-admin 中的证书验证?
【发布时间】:2018-05-13 20:56:27
【问题描述】:

如何避免 spring-boot-admin 中的证书验证?

链接错误图片: https://ibb.co/fkZu8y

我在一个类中配置了RestTemplate来避免证书,但是我不知道如何发送它,我猜它必须在客户端,spring-boot-admin-starter-client自动工作。

这是避免证书验证的代码。

public class SSLUtil {

    public RestTemplate getRestTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
        TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                return true;
            }
        };
        SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy)
                .build();
        SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        requestFactory.setHttpClient(httpClient);
        RestTemplate restTemplate = new RestTemplate(requestFactory);
        return restTemplate;
    }

}

Application.properties

spring.application.name=Admin-Application

server.port=1111

security.user.name=admin

security.user.password=admin123

@Configuration
    public static class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            // Page with login form is served as /login.html and does a POST on
            // /login
            http.formLogin().loginPage("/login.html").loginProcessingUrl("/login").permitAll();
            // The UI does a POST on /logout on logout
            http.logout().logoutUrl("/logout");
            // The ui currently doesn't support csrf
            http.csrf().disable().authorizeRequests()

                    // Requests for the login page and the static assets are
                    // allowed
                    // http.authorizeRequests()
                    .antMatchers("/login.html", "/**/*.css", "/img/**", "/third-party/**").permitAll();
            // ... and any other request needs to be authorized
            http.authorizeRequests().antMatchers("/**").authenticated();

            // Enable so that the clients can authenticate via HTTP basic for
            // registering
            http.httpBasic();
        }
    }

【问题讨论】:

    标签: spring-boot spring-boot-actuator spring-boot-admin


    【解决方案1】:

    我将 Spring Boot Admin 2.1.3 与 Eureka 一起使用。

    似乎 SBA 已从 RestTemplate 转移到 WebClient。所以我创建了一个 WebClient,它有一个 SSLContext,信任管理器设置为InsecureTrustManagerFactory,它信任一切。然后我使用这个 webclient 并实例化 SBA 的 InstanceWebClient。不确定是否有更简单的方法,但这对我有用。

    import de.codecentric.boot.admin.server.config.AdminServerProperties;
    import de.codecentric.boot.admin.server.web.client.HttpHeadersProvider;
    import de.codecentric.boot.admin.server.web.client.InstanceExchangeFilterFunction;
    import de.codecentric.boot.admin.server.web.client.InstanceWebClient;
    import io.netty.channel.ChannelOption;
    import io.netty.handler.ssl.SslContext;
    import io.netty.handler.ssl.SslContextBuilder;
    import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
    import io.netty.handler.timeout.ReadTimeoutHandler;
    import org.springframework.beans.factory.ObjectProvider;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.client.reactive.ReactorClientHttpConnector;
    import org.springframework.web.reactive.function.client.WebClient;
    import reactor.netty.ConnectionObserver;
    import reactor.netty.http.client.HttpClient;
    
    import javax.net.ssl.SSLException;
    import java.util.Collections;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    @Configuration
    @EnableConfigurationProperties(AdminServerProperties.class)
    public class SslConfiguration {
    
        private final AdminServerProperties adminServerProperties;
    
        public SslConfiguration(AdminServerProperties adminServerProperties) {
            this.adminServerProperties = adminServerProperties;
        }
    
    
        @Bean
        public InstanceWebClient instanceWebClient(HttpHeadersProvider httpHeadersProvider,
                                            ObjectProvider<List<InstanceExchangeFilterFunction>> filtersProvider) throws SSLException {
            List<InstanceExchangeFilterFunction> additionalFilters = filtersProvider.getIfAvailable(Collections::emptyList);
            return InstanceWebClient.builder()
                    .defaultRetries(adminServerProperties.getMonitor().getDefaultRetries())
                    .retries(adminServerProperties.getMonitor().getRetries())
                    .httpHeadersProvider(httpHeadersProvider)
                    .webClient(getWebClient())
                    .filters(filters -> filters.addAll(additionalFilters))
                    .build();
        }
    
        private WebClient getWebClient() throws SSLException {
            SslContext sslContext = SslContextBuilder
                    .forClient()
                    .trustManager(InsecureTrustManagerFactory.INSTANCE)
                    .build();
    
            HttpClient httpClient = HttpClient.create()
                    .compress(true)
                    .secure(t -> t.sslContext(sslContext))
                    .tcpConfiguration(tcp -> tcp.bootstrap(bootstrap -> bootstrap.option(
                            ChannelOption.CONNECT_TIMEOUT_MILLIS,
                            (int) adminServerProperties.getMonitor().getConnectTimeout().toMillis()
                    )).observe((connection, newState) -> {
                        if (ConnectionObserver.State.CONNECTED.equals(newState)) {
                            connection.addHandlerLast(new ReadTimeoutHandler(adminServerProperties.getMonitor().getReadTimeout().toMillis(),
                                    TimeUnit.MILLISECONDS
                            ));
                        }
                    }));
            ReactorClientHttpConnector reactorClientHttpConnector = new ReactorClientHttpConnector(httpClient);
    
            return WebClient.builder().clientConnector(reactorClientHttpConnector).build();
        }
    }
    

    【讨论】:

    • 嘿@crea1 我还需要覆盖 SBA 的实例 webclient 以通过 ssl 验证,因为我很难连接到 ssl 上的客户端。但是,您发布的代码不适用于 SBA 服务器版本 2.6.2。你有机会发布更新吗?非常感谢!
    • @ustad 似乎发生了很大变化(为什么我在原始答案中发布了版本)。不幸的是,我不再与 SBA 合作,所以我没有任何更新要分享。
    • 感谢@crea1 的回复,我实际上找到了一个解决方案,至少可以让管理服务器端连接回客户端,该解决方案直接来自他们的文档(SBA 管理版本 2.6.2):codecentric.github.io/spring-boot-admin/current/… 对于在客户端,我使用的是自定义休息模板,但 SBA 客户端似乎没有选择它,即使我看到 SBA 客户端代码正在使用 BlockingRegistrationClient 即)RestTemplate
    【解决方案2】:

    要禁止 SBA 管理服务器从它尝试连接的客户端验证 SSL 证书,您可以使用以下命令: 对于 SBA 版本 2.6.2,它或多或少地从他们的文档中概述:https://codecentric.github.io/spring-boot-admin/current/#_using_mutual_tls

    这是完整的配置覆盖 bean:

    package com.markham.mkmappadmin.config;
    
    import javax.net.ssl.SSLException;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.client.reactive.ClientHttpConnector;
    import org.springframework.http.client.reactive.ReactorClientHttpConnector;
    
    import io.netty.handler.ssl.SslContext;
    import io.netty.handler.ssl.SslContextBuilder;
    import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
    import reactor.netty.http.client.HttpClient;
    
    /**
     * Custom http client class which overrides Spring Boot Admin's server default client.<br>
     * The custom client will bypass any SSL Validation by configuring an instance of
     *  {@link InsecureTrustManagerFactory}
     * @author Hanif Rajabali
     * @see <a href="https://codecentric.github.io/spring-boot-admin/current/#_using_mutual_tls">Spring Boot Admin 2.6.2 Using Mutual TLS</a>
     */
    @Configuration
    public class CustomHttpClientConfig {
    
        @Bean
        public ClientHttpConnector customHttpClient() throws SSLException {
            SslContext sslContext = SslContextBuilder
                  .forClient()
                  .trustManager(InsecureTrustManagerFactory.INSTANCE)
                  .build();
            HttpClient httpClient = HttpClient.create().secure(
                ssl -> ssl.sslContext(sslContext)
            );
            return new ReactorClientHttpConnector(httpClient);
        }
    
    }
    

    我还没有弄清楚如何从 SBA 客户端禁用它。我在下面定义了一个自定义 RestTemplate Config,但即使我看到 SBA 客户端代码正在使用 BlockingRegistrationClient (即)RestTemplate,SBA 客户端似乎也没有选择它

    package com.markham.mkmemailerws.config;
    
    import java.security.KeyManagementException;
    import java.security.NoSuchAlgorithmException;
    import java.security.cert.X509Certificate;
    
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    
    import org.apache.http.conn.ssl.NoopHostnameVerifier;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.springframework.boot.web.client.RestTemplateBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
    import org.springframework.web.client.RestTemplate;
    
    /**
     * Need to explicitly build Spring Boot's auto configured
     * {@link #restTemplate(RestTemplateBuilder)}
     *
     * @author Hanif Rajabali
     *
     */
    @Configuration
    public class RestTemplateConfig {
    
    //   @Bean
    //   public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
    //      return restTemplateBuilder.build();
    //   }
    
    
        /**
         * The following will bypass ssl validation altogether. Not ideal.
         */
        @Bean
        public RestTemplate restTemplate(RestTemplateBuilder builder)
                throws NoSuchAlgorithmException, KeyManagementException {
    
            TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
    
                public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
                }
    
                public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
                }
            } };
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            CloseableHttpClient httpClient = HttpClients.custom().setSSLContext(sslContext)
                    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();
            HttpComponentsClientHttpRequestFactory customRequestFactory = new HttpComponentsClientHttpRequestFactory();
            customRequestFactory.setHttpClient(httpClient);
            return builder.requestFactory(() -> customRequestFactory).build();
        }
    }
    

    【讨论】:

      【解决方案3】:

      试试 http.csrf().disable().authorizeRequests() 上面的代码将禁用 csrf 令牌。下面是我的 OAuth 代码,我在其中禁用了 csrf 以降低复杂性。

      @RestController
      @EnableOAuth2Sso
      @EnableResourceServer
      @SpringBootApplication
      public class SpringBootWebApplication extends WebSecurityConfigurerAdapter {
                  @Override
                  protected void configure(HttpSecurity http) throws Exception {
      
                      http.csrf().disable().authorizeRequests()
      
                              .antMatchers("/api/**", "/dashboard", "/welcome","/about").authenticated().antMatchers("/**").permitAll()
                              .anyRequest().authenticated().and().logout().logoutSuccessUrl("/").permitAll();
      
                  }
      

      【讨论】:

      • 在我的SecurityConfig类中我已经禁用了csrf,spring-boot-admin中的错误是一样的:(
      猜你喜欢
      • 1970-01-01
      • 2015-01-22
      • 2014-11-25
      • 2011-04-25
      • 1970-01-01
      • 2016-08-21
      • 1970-01-01
      • 2015-11-22
      • 2020-10-15
      相关资源
      最近更新 更多