在 Android 或 Java 项目中使用 OkHttp 请求 HTTPS 接口时,如果目标服务器使用了 自签名证书,默认是无法建立连接的(因为证书不在系统信任链中)。我们需要手动 将自签名证书添加到 OkHttp 的信任列表中。


✅ 场景说明

  • 使用 OkHttp 访问 https://your.server.com
  • 该服务器使用了 自签名证书(不是 CA 机构签发)
  • 报错如:javax.net.ssl.SSLHandshakeException: ...

✅ 解决方案:信任指定证书(推荐)

你需要:

  1. 拿到 .cer 或 .crt 证书文件(Base64 编码)
  2. 加载该证书到 TrustManager
  3. 构造 OkHttp 的 SSLSocketFactory

🔐 示例代码(Java 或 Android 使用 OkHttp 3.x/4.x)

public OkHttpClient getUnsafeOkHttpClient(Context context) {
    try {
        // Step 1:从 assets 目录加载证书(cert.crt 为自签名证书)
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream caInput = context.getAssets().open("cert.crt");  // 放到 assets 目录
        Certificate ca = cf.generateCertificate(caInput);
        caInput.close();

        // Step 2:创建 KeyStore 并加入受信证书
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        // Step 3:创建 TrustManagerFactory
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        // Step 4:创建 SSLContext
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);

        // Step 5:构建 OkHttpClient
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) tmf.getTrustManagers()[0])
                .hostnameVerifier((hostname, session) -> true);  // 可选:关闭主机名验证(开发用)

        return builder.build();

    } catch (Exception e) {
        e.printStackTrace();
        return new OkHttpClient();  // 失败返回默认客户端
    }
}

✅ 证书获取方式

  1. 浏览器访问服务器,点 HTTPS 小锁 → 查看证书 → 导出为 .crt
  2. 或使用命令行提取:
openssl s_client -connect your.server.com:443 -showcerts

复制其中的 -----BEGIN CERTIFICATE----- 到 -----END CERTIFICATE----- 部分,保存为 cert.crt


✅ cert.crt 放置路径(Android)

  • 放到 assets/ 文件夹中
  • 保证文件名与代码中的一致

⚠️ 注意事项

  • 不要在生产中使用 hostnameVerifier((hostname, session) -> true),这会绕过域名校验(有安全风险)
  • 自签证书方案更适合内网通信、开发调试环境

✅ 需要更安全/灵活的方式?

可以用 [OkHttp + 自定义 TrustManager + 多证书信任链] 或 结合 [BouncyCastle] 提高安全性。告诉我你的需求:

  • 是否部署在 Android 或 Java 后端?
  • 是否需要支持多个自签名证书?
  • 是否希望与 Retrofit 集成?

好的!以下是一个 完整的 OkHttp 客户端,包含了如何在 Android 或 Java 项目中处理 自签名证书,并确保所有的 HTTPS 请求都能信任你的自签名证书。


📁 项目结构

  • assets/cert.crt — 你的自签名证书文件,放在 Android 项目的 assets 文件夹里。
  • 通过 OkHttp 通过 TrustManager 实现自签名证书的信任。

🔐 完整代码:自签名证书信任设置

Step 1: 创建 UnsafeOkHttpClient.java

import android.content.Context;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

public class UnsafeOkHttpClient {

    public static OkHttpClient getUnsafeOkHttpClient(Context context) {
        try {
            // 1. 从 assets 加载自签名证书文件
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            InputStream caInput = context.getAssets().open("cert.crt");  // 放置证书文件在 assets 目录
            Certificate ca = cf.generateCertificate(caInput);
            caInput.close();

            // 2. 将证书加入到 KeyStore
            String keyStoreType = KeyStore.getDefaultType();
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
            keyStore.load(null, null);
            keyStore.setCertificateEntry("ca", ca);

            // 3. 创建 TrustManagerFactory 并初始化
            String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
            tmf.init(keyStore);

            // 4. 使用 SSLContext 设置自签名证书
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, tmf.getTrustManagers(), null);

            // 5. 创建 OkHttpClient,配置 SSL 和自定义的 TrustManager
            OkHttpClient.Builder builder = new OkHttpClient.Builder()
                    .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) tmf.getTrustManagers()[0])
                    .hostnameVerifier((hostname, session) -> true);  // 默认信任所有主机名,适合开发环境

            return builder.build();

        } catch (Exception e) {
            e.printStackTrace();
            return new OkHttpClient();  // 如果失败,则返回默认 OkHttpClient
        }
    }

    // 使用 OkHttpClient 发起 HTTPS 请求示例
    public static void makeRequest(Context context) {
        OkHttpClient client = getUnsafeOkHttpClient(context);
        Request request = new Request.Builder()
                .url("https://your.server.com")  // 你的服务器地址
                .build();

        client.newCall(request).enqueue(new okhttp3.Callback() {
            @Override
            public void onFailure(okhttp3.Call call, java.io.IOException e) {
                e.printStackTrace();
            }

            @Override
            public void onResponse(okhttp3.Call call, Response response) throws java.io.IOException {
                if (response.isSuccessful()) {
                    System.out.println("Response: " + response.body().string());
                } else {
                    System.out.println("Request failed!");
                }
            }
        });
    }
}

Step 2: 在 MainActivity.java 中调用

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 调用自定义 OkHttp 客户端进行 HTTPS 请求
        UnsafeOkHttpClient.makeRequest(this);
    }
}

📂 资源文件

1. assets/cert.crt — 你的自签名证书文件(Base64 编码的 .crt

将自签名证书文件 cert.crt 放到 assets 目录下。

获取证书的方式:

  • 浏览器:右键点击 HTTPS 页面,查看证书并导出为 .crt 文件。
  • 命令行:运行 openssl 命令来提取证书:
openssl s_client -connect your.server.com:443 -showcerts

复制证书内容并保存为 .crt 文件。


🛠️ 运行示例:

  1. 将 cert.crt 放入 Android 项目的 assets 文件夹。
  2. 在 MainActivity 中调用 UnsafeOkHttpClient.makeRequest() 方法发起请求。
  3. 在 Android 模拟器或真机上运行该应用,OkHttp 会通过自签名证书与服务器建立 HTTPS 连接。

⚠️ 注意事项:

  • 生产环境不建议绕过主机名验证:在生产环境中,不应该绕过 hostnameVerifier,你需要确保服务器的域名正确。
  • 适用于 开发、内网环境 或 自签证书 测试。