解决“javax.net.ssl.SSLPeerUnverifiedException: Hostname 192.168.1.110 not verifie”的问题

作为一名经验丰富的开发者,你可以向刚入行的小白解释如何解决“javax.net.ssl.SSLPeerUnverifiedException: Hostname 192.168.1.110 not verified”问题。以下是一个详细的步骤和相应的代码示例。

流程图

flowchart TD
    A[创建 SSLContext 实例] --> B[创建 TrustManager 实例]
    B --> C[初始化 KeyStore]
    C --> D[创建 SSLContext]
    D --> E[创建 SSLSocketFactory]
    E --> F[创建 HostnameVerifier]
    F --> G[设置 HostnameVerifier]
    G --> H[创建 HttpsURLConnection]
    H --> I[设置 SSLSocketFactory]
    H --> J[设置 HostnameVerifier]

步骤

  1. 创建 SSLContext 实例:SSLContext 类用于创建 SSL/TLS 安全套接字。你可以使用其中一个 getInstance 方法来获取 SSLContext 实例。
SSLContext sslContext = SSLContext.getInstance("TLS");
  1. 创建 TrustManager 实例:TrustManager 是一个接口,用于验证远程服务器的证书。X509TrustManager 是 TrustManager 的一个实现类,它可以接受任何证书。
TrustManager[] trustManagers = new TrustManager[]{new X509TrustManager() {
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        // 不验证客户端证书
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        // 不验证服务器证书
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
}};
  1. 初始化 KeyStore:KeyStore 用于存储证书和私钥。在这个步骤中,我们需要加载一个空的 KeyStore。
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
  1. 创建 SSLContext:使用 SSLContext 的 init 方法将 TrustManager 初始化,并将其传递给 SSLContext。
sslContext.init(null, trustManagers, new SecureRandom());
  1. 创建 SSLSocketFactory:SSLSocketFactory 是用于创建 SSL/TLS 安全套接字的工厂类。我们可以使用 SSLContext 的 getSocketFactory 方法来获取 SSLSocketFactory 实例。
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
  1. 创建 HostnameVerifier:HostnameVerifier 用户验证主机名是否匹配服务器证书中的主机名。
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
    @Override
    public boolean verify(String hostname, SSLSession session) {
        // 不验证主机名
        return true;
    }
};
  1. 设置 HostnameVerifier:在创建 HttpsURLConnection 之前,需要将刚才创建的 HostnameVerifier 设置为默认的 HostnameVerifier。
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
  1. 创建 HttpsURLConnection:HttpsURLConnection 是用于进行 HTTPS 请求的类。
URL url = new URL("
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
  1. 设置 SSLSocketFactory:将刚才创建的 SSLSocketFactory 设置为 HttpsURLConnection 的 SSLSocketFactory。
connection.setSSLSocketFactory(sslSocketFactory);
  1. 设置 HostnameVerifier:将刚才创建的 HostnameVerifier 设置为 HttpsURLConnection 的 HostnameVerifier。
connection.setHostnameVerifier(hostnameVerifier);

代码示例

import javax.net.ssl.*;
import java.io.IOException;
import java.net.URL;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class SSLExample {

    public static void main(String[] args) throws Exception {
        // 创建 SSLContext 实例
        SSLContext sslContext = SSLContext.getInstance("TLS");

        // 创建 TrustManager 实例
        TrustManager[] trustManagers = new TrustManager[]{new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                // 不验证客户端证书
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                // 不验证服务器证书
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return