Android9下OkHttp2.6如何配置使用OpenSSL引擎实现HTTPS?
OkHttp2.6 集成自定义OpenSSL引擎适配Android9 HTTPS改造方案
问题1:OkHttp默认BoringSSL能否调用OpenSSL引擎?是否需要替换?
OkHttp 2.6在Android平台默认依赖系统SSL实现(Android 9的系统SSL基于OpenSSL分支,但与标准OpenSSL存在API差异);若使用OkHttp自带的BoringSSL,则无法直接调用标准OpenSSL引擎——因为BoringSSL移除了OpenSSL引擎体系的部分核心API,与标准引擎接口不兼容。
必须执行的操作:替换为标准OpenSSL库
- 编译适配Android9的标准OpenSSL库(推荐1.1.1系列,覆盖armeabi-v7a、arm64-v8a等目标架构),生成动态链接库(
.so)。 - 将你的自定义OpenSSL引擎编译为适配Android的
.so,编译时依赖上述标准OpenSSL库的头文件和链接库。 - 将编译好的OpenSSL和自定义引擎
.so文件放入APK的jniLibs对应架构目录下。
问题2:OkHttp中指定OpenSSL引擎的实现步骤
核心思路是通过JNI封装OpenSSL引擎的调用逻辑,自定义SSLSocketFactory并注入OkHttp的配置中。
步骤1:JNI层封装引擎初始化与SSL上下文创建
编写C/C++代码,完成引擎加载、初始化,并创建OpenSSL的SSL_CTX,暴露给Java层调用:
#include <jni.h> #include <openssl/ssl.h> #include <openssl/engine.h> #include <openssl/crypto.h> JNIEXPORT jlong JNICALL Java_com_your_package_SSLNative_getCustomSSLContext(JNIEnv *env, jobject thiz) { // 初始化OpenSSL引擎系统 ENGINE_load_builtin_engines(); // 加载自定义引擎(替换为你的引擎ID) ENGINE *engine = ENGINE_by_id("your_custom_engine_id"); if (!engine) { return 0; } // 初始化引擎 if (!ENGINE_init(engine)) { ENGINE_free(engine); return 0; } // 设置引擎为默认算法提供者(覆盖所有加密算法类型) ENGINE_set_default(engine, ENGINE_METHOD_ALL); // 创建TLS上下文 SSL_CTX *ctx = SSL_CTX_new(TLS_method()); if (!ctx) { ENGINE_finish(engine); ENGINE_free(engine); return 0; } // 配置信任链(可根据需求加载自定义证书或使用系统默认路径) SSL_CTX_set_default_verify_paths(ctx); // 注意:引擎资源需在Java层销毁时释放,此处暂存ctx指针返回 return (jlong)ctx; } JNIEXPORT void JNICALL Java_com_your_package_SSLNative_releaseSSLContext(JNIEnv *env, jobject thiz, jlong ctxPtr) { if (ctxPtr != 0) { SSL_CTX *ctx = (SSL_CTX *)ctxPtr; SSL_CTX_free(ctx); ENGINE_cleanup(); } }
步骤2:Java层封装SSLSocketFactory
编写工具类,通过JNI调用底层逻辑,生成OkHttp可用的SSLSocketFactory:
package com.your.package; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; public class SSLUtils { static { // 加载OpenSSL和自定义引擎动态库 System.loadLibrary("openssl"); System.loadLibrary("your_custom_engine"); } private static native long getCustomSSLContext(); private static native void releaseSSLContext(long ctxPtr); public static SSLSocketFactory getCustomSSLSocketFactory() { long ctxPtr = getCustomSSLContext(); if (ctxPtr == 0) { throw new RuntimeException("Failed to initialize custom SSL engine"); } // 通过JNI辅助转换SSL_CTX到Java层SSLContext(或直接在JNI封装SSLSocket创建逻辑) // 此处简化示例,实际需根据OpenSSL与Java SSL的绑定逻辑实现转换 SSLContext sslContext = ...; // 完成ctxPtr到SSLContext的转换 return sslContext.getSocketFactory(); } }
步骤3:配置OkHttpClient使用自定义SSLSocketFactory
修改OkHttp客户端初始化代码,替换默认的SSL组件:
OkHttpClient client = new OkHttpClient.Builder() .sslSocketFactory(SSLUtils.getCustomSSLSocketFactory()) // 生产环境需实现合规的HostnameVerifier,此处为测试示例 .hostnameVerifier((hostname, session) -> true) .build();
额外注意事项
- Android9的网络安全配置:若使用自定义证书,需在
res/xml/network_security_config.xml中配置信任该证书,避免SSL验证失败。 - 动态库架构适配:确保编译的
.so覆盖应用目标设备的CPU架构,避免UnsatisfiedLinkError。 - 资源释放:在应用退出时,调用
releaseSSLContext释放OpenSSL引擎和上下文资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Jermynn Z
相关产品推荐
相关产品推荐

