API自定义SSL证书配置:Volley在Android API 24报SSL握手错误
原因说明
该报错是因为API Level 24(Android 7.0)的系统预装根证书列表未收录你所请求站点的SSL证书对应的CA根证书,而API Level 30(Android 11)及以上版本的系统更新了根证书列表,因此可以正常完成证书校验。浏览器访问无异常是因为浏览器会自行维护独立的根证书列表,不受系统根证书版本限制。
解决方案
方案一:配置网络安全规则内置信任证书(推荐,安全无风险)
该方案仅对你指定的站点信任内置的证书,不会引入全局安全风险,无需修改业务代码。
操作步骤:
- 导出目标站点的根CA证书:通过浏览器访问API地址,点击地址栏的安全锁标识,在证书详情中导出根证书,保存为PEM格式(后缀为
.crt或.pem均可)。 - 在项目
res目录下新建raw文件夹,将导出的证书文件放入该目录,注意文件名只能包含小写字母、数字和下划线。 - 在
res/xml目录下新建network_security_config.xml文件,写入如下配置:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <!-- 替换为你的API站点域名,includeSubdomains设为true表示信任所有子域名 --> <domain includeSubdomains="true">subdomain.the.url</domain> <trust-anchors> <!-- 替换为你放在raw目录下的证书文件名,无需加后缀 --> <certificates src="@raw/your_cert_file_name" /> <!-- 保留系统根证书信任,不影响其他常规请求 --> <certificates src="system" /> </trust-anchors> </domain-config> </network-security-config>
- 打开项目的
AndroidManifest.xml,在<application>标签中添加配置引用:
<application ... android:networkSecurityConfig="@xml/network_security_config" ...>
配置完成后重新打包即可,原有Volley请求代码无需修改。
方案二:自定义SSL校验逻辑(仅测试使用,禁止正式环境使用)
如果只是临时调试,可以采用信任所有证书的方案,该方案会绕过所有SSL校验,存在严重的中间人攻击风险,正式上线请勿使用。
操作步骤:
- 新增自定义Volley请求队列构造方法:
import android.content.Context import com.android.volley.RequestQueue import com.android.volley.toolbox.HurlStack import com.android.volley.toolbox.Volley import javax.net.ssl.SSLContext import javax.net.ssl.TrustManager import javax.net.ssl.X509TrustManager fun createUnsafeVolleyQueue(context: Context): RequestQueue { // 构造信任所有证书的TrustManager val trustAllManager = object : X509TrustManager { override fun checkClientTrusted(p0: Array<out java.security.cert.X509Certificate>?, p1: String?) {} override fun checkServerTrusted(p0: Array<out java.security.cert.X509Certificate>?, p1: String?) {} override fun getAcceptedIssuers(): Array<java.security.cert.X509Certificate> = emptyArray() } val sslContext = SSLContext.getInstance("TLS") sslContext.init(null, arrayOf<TrustManager>(trustAllManager), null) val sslSocketFactory = sslContext.socketFactory // 用自定义的SSLSocketFactory构造HurlStack,再初始化Volley队列 val hurlStack = HurlStack(null, sslSocketFactory) return Volley.newRequestQueue(context, hurlStack) }
- 替换原有请求队列初始化代码:
// 替换原有Volley.newRequestQueue调用 val requestQueue = createUnsafeVolleyQueue(this.context) requestQueue.add(JsonArrayRequest("https://subdomain.the.url", { response -> // 处理响应 }, { volleyError -> // 处理错误 } ))
内容的提问来源于stack exchange,提问作者isi_ko
相关产品推荐
相关产品推荐

