You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 8.0+证书路径信任锚缺失异常,适配targetSdkVersion26方案咨询

解决Android 8.0+ SSL握手失败(CertPathValidatorException)问题

嘿,这个问题我之前帮不少开发者踩过坑,本质是Android 7.0(API 24)及以上系统对SSL证书验证的机制做了严格调整,再加上你项目里用的是已经被官方弃用的Apache HttpClient,才导致了这种跨版本兼容性问题。下面给你几个符合生产环境要求(targetSdkVersion≥26)的解决方案:

方案一:替换Apache HttpClient为OkHttp(推荐)

Android 6.0(API 23)之后,官方就不再维护Apache HttpClient了,转而推荐使用OkHttp或者HttpURLConnection,它们对高版本系统的SSL验证支持更完善,代码也更简洁。

举个简单的OkHttp GET请求示例:

OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
        .url("你的接口地址")
        .build();

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

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        if (response.isSuccessful()) {
            String responseData = response.body().string();
            // 处理响应数据
        }
    }
});

OkHttp默认会自动验证合法的SSL证书,如果你的服务器证书是权威CA颁发的,直接用这个就能解决问题;如果是自签名证书,也可以通过自定义TrustManager来配置信任,安全性更高。

方案二:保留Apache HttpClient,修复SSL验证逻辑

如果因为历史原因必须保留Apache HttpClient,那需要自定义SSLSocketFactory,手动配置信任的证书链,绝对禁止在生产环境使用“信任所有证书”的不安全代码。步骤如下:

  1. 导入服务器证书:把服务器的CA证书(.crt或.pem格式)放到项目的res/raw目录下。
  2. 编写SSL工具类:加载证书并创建自定义TrustManager:
public class SSLUtils {
    public static SSLSocketFactory getSSLSocketFactory(Context context) throws Exception {
        // 加载证书
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream certInputStream = context.getResources().openRawResource(R.raw.your_cert);
        Certificate ca;
        try {
            ca = cf.generateCertificate(certInputStream);
        } finally {
            certInputStream.close();
        }

        // 创建KeyStore
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

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

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

        return new SSLSocketFactory(sslContext);
    }
}
  1. 替换HttpClient的SSLSocketFactory:
HttpClient httpClient = new DefaultHttpClient();
try {
    SSLSocketFactory sslSocketFactory = SSLUtils.getSSLSocketFactory(context);
    Scheme scheme = new Scheme("https", sslSocketFactory, 443);
    httpClient.getConnectionManager().getSchemeRegistry().register(scheme);
} catch (Exception e) {
    e.printStackTrace();
}
// 用这个httpClient发起请求

方案三:检查服务器端证书链完整性

有时候问题出在服务器端:Android 8.0+对SSL证书链的完整性要求更严格,如果服务器只配置了叶子证书,没有配置中间证书,就会导致高版本系统无法找到信任锚点。你可以用SSL证书检测工具检查服务器的证书链是否完整,若不完整,联系服务器运维人员补全中间证书即可。

为什么targetSdkVersion=21能解决?

因为API 21时,Apache HttpClient还是系统默认的网络库,证书验证逻辑相对宽松;而API 24+系统引入了网络安全配置(Network Security Configuration),同时Apache HttpClient被移到了org.apache.http.legacy库,旧的验证逻辑在高targetSdk下不再兼容,所以设置为21能临时规避,但不符合生产环境要求。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:09:26