httpRequest.request 请求https接口ssl证书验证失败,如何解决?

https接口httpRequest.request请求报错:“SSL peer certificate or SSH remote key was not OK”。

请问:

  1. httpRequest.request怎样进行证书验证。
  2. httpRequest.request能否忽略证书认证访问https接口。
阅读 942
avatarAI BotBETA
  1. HttpRequest.request怎样进行证书验证。

HttpRequest.request的证书验证通常依赖于底层的HTTP库,如Apache HttpClient或OkHttp。这些库在建立SSL连接时,会使用Java的SSL套接字工厂(SSLSocketFactory)来验证服务器的SSL证书。

如果你想要自定义证书验证,你需要创建一个自定义的SSLSocketFactory,然后将其设置到HttpClient或OkHttp的配置中。在创建自定义SSLSocketFactory时,你可以指定信任的证书和密钥库。

以下是一个使用Apache HttpClient的示例:

try {
    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    keyStore.load(new FileInputStream("my_cert.jks"), "password".toCharArray());

    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    trustManagerFactory.init(keyStore);

    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, trustManagerFactory.getTrustManagers(), null);

    CloseableHttpClient httpClient = HttpClients.custom()
            .setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE))
            .build();

    HttpGet httpGet = new HttpGet("https://example.com");
    CloseableHttpResponse response = httpClient.execute(httpGet);
    // handle response
} catch (Exception e) {
    e.printStackTrace();
}

在这个示例中,我们创建了一个自定义的KeyStore,它包含了我们的证书。然后,我们创建了一个TrustManagerFactory,它使用这个KeyStore来生成TrustManagers。最后,我们创建了一个SSLContext,它使用这些TrustManagers来初始化。

然后,我们使用这个SSLContext创建了一个自定义的SSLConnectionSocketFactory,并设置到了HttpClient中。

注意,NoopHostnameVerifier.INSTANCE是一个不验证主机名的HostnameVerifier,它应该只用于测试环境。在生产环境中,你应该使用默认的HostnameVerifier或自定义的验证主机名的HostnameVerifier。

  1. HttpRequest.request能否忽略证书认证访问https接口。

是的,HttpRequest.request可以配置为忽略SSL证书验证。但是,这通常不推荐在生产环境中使用,因为它会使你的连接容易受到中间人攻击。

如果你确实需要忽略证书验证,你可以创建一个自定义的HostnameVerifier和TrustManager,然后将它们设置到HttpClient或OkHttp的配置中。

以下是一个使用Apache HttpClient的示例:

try {
    TrustManager[] trustAllCerts = new TrustManager[] {
        new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
            }
            public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
            }
        }
    };

    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

    HostnameVerifier allHostsValid = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };
    HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);

    URL url = new URL("https://example.com");
    HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
    // handle connection
} catch (Exception e) {
    e.printStackTrace();
}

在这个示例中,我们创建了一个自定义的TrustManager,它接受所有的证书。然后,我们创建了一个SSLContext,它使用这个TrustManager来初始化。最后,我们将这个SSLContext的SocketFactory设置为了默认的SSLSocketFactory,并将一个接受所有主机名的HostnameVerifier设置为了默认的HostnameVerifier。

但是,请注意,这种方法会使你的连接容易受到中间人攻击,因此只应在测试环境中使用。在生产环境中,你应该使用有效的证书和正确的证书验证。

1 个回答

HTTPS证书是一种数字证书,这种证书的主要作用是保护网站安全性。HTTPS证书校验则是指在建立HTTPS连接时对证书进行校验,保证连接的安全性,使网站的安全性更高。

HTTPS校验主要包括以下几个步骤:

  1. 客户端向服务器发送HTTPS请求
  2. 服务器返回SSL证书
  3. 客户端对证书进行校验
  4. 如果验证通过,客户端和服务器之间就建立起了安全的HTTPS连接。

本题中的报错出现在第三步,即客户端对证书校验报错。

客户端对证书的校验验证SSL证书的四个方面:

  1. 检查SSL证书是否是由浏览器中“受信任的根证书颁发机构”颁发。
  2. 检查SSL证书中的证书吊销列表,检查证书是否被证书颁发机构吊销。
  3. 检查此SSL证书是否过期。
  4. 检查部署此SSL证书校验的网站域名和证书域名是否一致。

客户端如果没有对证书进行校验,就会导致中间人攻击,中间人攻击分两种:SSL劫持和SSL剥离。

SSL劫持原理:第三方攻击者会先把自己接到请求方和接收方之间,然后通过自己伪造的证书先模拟成接收方和请求方交换数据,然后再模拟自己为请求方与接收方进行数据交互。一般SSL劫持容易被用于使用者在自己的浏览器等地方安装了未被权威CA认证的证书,因此需要进行证书校验。

image.png

SSL剥离通常发生在HTTP请求中,不过现在的网站大部分强制使用HTTPS访问网站,这里不再赘述。

问题1:开发者应对服务端的证书进行上述四个方面的检查,确认无误。若服务端证书是自定义的CA,即SSL证书不是由浏览器中“受信任的根证书颁发机构”颁发,可以通过使用httpRequest.request接口的HttpRequestOptions参数中的caPath设置自定义CA的路径,如果设置了此参数,系统将使用用户指定路径的CA证书,(开发者需保证该路径下CA证书的可访问性),否则将使用系统预设CA证书,系统预设CA证书位置:/etc/ssl/certs/cacert.pem。

问题2:客户端需要对证书进行验证,否则会导致中间人攻击。

参考链接

API参考:HttpRequestOptions

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进