仅使用 https 启动 Spring - 测试失败

问题描述

我有 spring boot - angular 应用程序

我的服务器端口是 1234(示例)。

但现在我已经设置了 ssl

步骤:

使用 keytool 创建自签名证书并将我的 p12 证书文件添加到资源文件夹中

更新了 application.properties

server.ssl.key-store-type=PKCS12

server.ssl.key-store=classpath:myfile.p12

server.ssl.key-store-password=somepasswordfromenv

server.ssl.key-alias=myalias

server.ssl.enabled=true

http.port=8080

server.port=8443

启动应用并测试

@SpringBoottest(classes = AppWithoutBeansApplication.class,webEnvironment = WebEnvironment.DEFINED_PORT)
class AppControllerTest {

    @Value("${server.ssl.key-store}")
    private Resource trustStore;

    @Value("${server.ssl.key-store-password}")
    private String trustStorePassword;

@Test
public void givenAcceptingallCertificatesUsing4_4_whenUsingRestTemplate_thenCorrect() 
throws ClientProtocolException,IOException {
    
    String urloverHttps = "https://localhost:8443/";
    CloseableHttpClient httpClient
      = HttpClients.custom()
        .setSSLHostnameVerifier(new NoopHostnameVerifier())
        .build();
    HttpComponentsClientHttpRequestFactory requestFactory 
      = new HttpComponentsClientHttpRequestFactory();
    requestFactory.setHttpClient(httpClient);

    ResponseEntity<String> response 
      = new RestTemplate(requestFactory).exchange(
      urloverHttps,HttpMethod.GET,null,String.class);
    assertthat(response.getStatusCode().value(),equalTo(200));
}   

...

错误

org.springframework.web.client.ResourceAccessException:对“https://localhost:8443/”的 GET 请求出现 I/O 错误:证书不匹配任何主题替代名称:[];嵌套异常是 javax.net.ssl.SSLPeerUnverifiedException:证书不匹配任何主题替代名称:[] 在 org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:746)

不明白我的集成测试是如何工作的

解决方法

所有答案看起来都很相似,但这一个有效

Ignore SSL certificate validation when using Spring RestTemplate

@Bean
public RestTemplate restTemplate() throws GeneralSecurityException {

    TrustStrategy acceptingTrustStrategy = (cert,authType) -> true;
    SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null,acceptingTrustStrategy).build();
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,NoopHostnameVerifier.INSTANCE);

    Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
            .register("https",sslsf).register("http",new PlainConnectionSocketFactory()).build();

    BasicHttpClientConnectionManager connectionManager = new BasicHttpClientConnectionManager(
            socketFactoryRegistry);
    CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
            .setConnectionManager(connectionManager).build();

    HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);

    RestTemplate restTemplate = new RestTemplate(requestFactory);

    return restTemplate;
}

看起来这部分有所不同

 *Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("https",new PlainConnectionSocketFactory()).build();*

不要使用这个

//  @Bean
//    public RestTemplate nonsslrestTemplate() throws KeyManagementException,NoSuchAlgorithmException,KeyStoreException {
//         TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain,String authType) -> true;
//         SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(null,acceptingTrustStrategy).build();
//         SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
//         CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();
//         HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
//         requestFactory.setHttpClient(httpClient);
//       return new RestTemplate(requestFactory);
//    }