在 Android 或 Java 项目中使用 OkHttp 请求 HTTPS 接口时,如果目标服务器使用了 自签名证书,默认是无法建立连接的(因为证书不在系统信任链中)。我们需要手动 将自签名证书添加到 OkHttp 的信任列表中。
✅ 场景说明
- 使用 OkHttp 访问
https://your.server.com
- 该服务器使用了 自签名证书(不是 CA 机构签发)
- 报错如:
javax.net.ssl.SSLHandshakeException: ...
✅ 解决方案:信任指定证书(推荐)
你需要:
- 拿到
.cer
或.crt
证书文件(Base64 编码) - 加载该证书到
TrustManager
- 构造 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(); // 失败返回默认客户端
}
}
✅ 证书获取方式
- 浏览器访问服务器,点 HTTPS 小锁 → 查看证书 → 导出为
.crt
- 或使用命令行提取:
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
文件。
🛠️ 运行示例:
- 将
cert.crt
放入 Android 项目的assets
文件夹。 - 在
MainActivity
中调用UnsafeOkHttpClient.makeRequest()
方法发起请求。 - 在 Android 模拟器或真机上运行该应用,OkHttp 会通过自签名证书与服务器建立 HTTPS 连接。
⚠️ 注意事项:
- 生产环境不建议绕过主机名验证:在生产环境中,不应该绕过
hostnameVerifier
,你需要确保服务器的域名正确。 - 适用于 开发、内网环境 或 自签证书 测试。
发表回复