首页 > 解决方案 > “没有主题替代 DNS 名称匹配发现”使用 RestTemplate 时出错

问题描述

我一直在尝试将 RestTemplate 请求发送到如下所示的 API url:

https://api.something.hostname.net/api/key=key&parameter1=val1&etc

它应该返回一个 JSON 响应。但它会给出以下错误: javax.net.ssl.SSLPeerUnverifiedException: Certificate for <api.something.hostname.net> doesn't match any of the subject alternative names: [sni-required.hostname.com]

然后我将实现我自己的 RestTemplate 如下(来自此链接):

public RestTemplate getRestTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException, CertificateException {


        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();

        requestFactory.setHttpClient(createAcceptSelfSignedCertificateClient());

        RestTemplate restTemplate = new RestTemplate(requestFactory);


        return restTemplate;
    }


    private static CloseableHttpClient createAcceptSelfSignedCertificateClient()
            throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {

        // use the TrustSelfSignedStrategy to allow Self Signed Certificates
        SSLContext sslContext = SSLContextBuilder
                .create()
                .loadTrustMaterial(new TrustSelfSignedStrategy())
                .build();

        // we can optionally disable hostname verification.
        // if you don't want to further weaken the security, you don't have to include this.
        HostnameVerifier allowAllHosts = new NoopHostnameVerifier();

        // create an SSL Socket Factory to use the SSLContext with the trust self signed certificate strategy
        // and allow all hosts verifier.
        SSLConnectionSocketFactory connectionFactory = new SSLConnectionSocketFactory(sslContext, allowAllHosts);

        // finally create the HttpClient using HttpClient factory methods and assign the ssl socket factory
        return HttpClients
                .custom()
                .setSSLSocketFactory(connectionFactory)
                .build();
    }

现在它抛出:

Caused by: java.security.cert.CertificateException: No subject alternative DNS name matching api.rasp.yandex.net found.
    at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:214) ~[na:1.8.0_172]
    at sun.security.util.HostnameChecker.match(HostnameChecker.java:96) ~[na:1.8.0_172]
    at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455) ~[na:1.8.0_172]
    at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:436) ~[na:1.8.0_172]
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:200) ~[na:1.8.0_172]
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124) ~[na:1.8.0_172]
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1596) ~[na:1.8.0_172]
    ... 56 common frames omitted

链接示例使用HttpClient 成功请求。我可以解决 RestTemplate 的问题还是必须转到 HttpClient 上?

如何在开发阶段暂时禁用 SSL 检查?这是可以在本地解决的问题还是API提供者的证书问题?

标签: javaspringapachespring-bootssl

解决方案


推荐阅读