ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

OkHttp Security Providers 深度指南:JVM、Android 与 GraalVM 的 TLS/HTTP/2 能力全景

OkHttp Security Providers 深度指南:JVM、Android 与 GraalVM 的 TLS/HTTP/2 能力全景 OkHttp Security Providers 深度指南JVM、Android 与 GraalVM 的 TLS/HTTP/2 能力全景【免费下载链接】okhttpA meticulous HTTP client for the JVM, Android, and GraalVM.项目地址: https://gitcode.com/gh_mirrors/okh/okhttp导读Security Providers 是 OkHttp 官方安全文档中对「TLS 与 HTTP/2 能力矩阵」的权威说明回答了同一个问题在 JVM、Android、GraalVM 以及 Bouncy Castle、Conscrypt、OpenJSSE、Corretto 等第三方安全提供者Security Provider之上OkHttp 分别能拿到哪些协议能力。读完本文你将掌握每个提供者的 HTTP/2 与 TLSv1.3 支持情况、OkHttp 底层如何按优先级自动探测并选用平台实现、如何通过把 Provider 注册到首位来切换 TLS 引擎以及各类限制与已知跟踪问题。一、Provider 能力总览表原文核心下表是官方文档给出的完整能力矩阵是所有后续讨论的事实基础ProviderHTTP/2TLSv1.3Powered ByNotesJVM defaultJava 9Java 11[OpenJDK]Android default✅Android 10[BoringSSL][GraalVM]✅[OpenJDK]Only actively tested with JDK 11, not with 8 target[Bouncy Castle]✅[Bouncy Castle][Tracking bug.][bug5698][Conscrypt]✅✅[BoringSSL]Activated if Conscrypt is first registered provider.[OpenJSSE]✅[OpenJDK]OpenJDK backport.[Corretto]✅✅[OpenSSL]Amazons high-performance provider. [Tracking bug.][bug5592]关键公共基线所有 Provider 均支持 HTTP/1.1 与 TLSv1.2。解读这张表需要注意三点能力是「平台提供」而非「OkHttp 实现」HTTP/2 依赖 ALPN 协商TLSv1.3 依赖底层 SSLContext 实现OkHttp 自身不实现 TLS它只是把能力翻译成自己的Protocol与TlsVersion模型。「✅」与「版本号」含义不同Java 9、Android 10、Java 11表示能力随运行平台版本渐进出现单独的 ✅ 表示在该 Provider 选型下该能力默认可用如 Conscrypt/Corretto 同时点亮两列。两处 Tracking bugBouncy Castle 与 Corretto 各有一个跟踪缺陷官方在能力标注后明确挂出了跟踪问题链接说明这两者在某些场景下有已知边界详见下文第五节。二、OkHttp 如何选择 Security ProviderPlatformRegistry 源码级解析从源码结构看OkHttp 的 JVM 端平台探测集中在 PlatformRegistry.kt 的findPlatform()中其选择逻辑严格遵循「第一个 Security Provider 是谁」这一标准private val isConscryptPreferred: Boolean get() { val preferredProvider Security.getProviders()[0].name return Conscrypt preferredProvider } // 同理还有 isOpenJSSEPreferredOpenJSSE与 isBouncyCastlePreferredBCfindPlatform()的完整决策链为若Security.getProviders()[0]名为Conscrypt则尝试ConscryptPlatform.buildIfSupported()否则若首位名为BC尝试BouncyCastlePlatform.buildIfSupported()否则若首位名为OpenJSSE尝试OpenJSSEPlatform.buildIfSupported()然后回退到Jdk9Platform.buildIfSupported()对应 JDK 9 或 JDK 8u251 之类带 ALPN 的 JDK再回退到Jdk8WithJettyBootPlatform.buildIfSupported()JDK 8 早期版本 Jetty ALPN boot最后兜底返回基础Platform()。这就是文档中「Activated if Conscrypt is first registered provider」的实现依据Conscrypt 必须被注册为第一个 Provider 才会被 OkHttp 采用Bouncy Castle 与 OpenJSSE 同理分别要求首位名为BC与OpenJSSE。因此在实际应用中激活第三方 TLS 引擎的标准做法是在创建OkHttpClient之前用Security.insertProviderAt(provider, 1)把目标 Provider 插到首位。三、七大 Provider 逐一深入1. JVM defaultOpenJDKJVM 默认平台是 OpenJDK 安全组实现HTTP/2 需要 Java 9ALPN 被合入 JDK 9TLSv1.3 需要 Java 11。在PlatformRegistry中对应Jdk9Platform分支这也是所有 JVM 应用的基线路径。2. Android defaultBoringSSLAndroid 内置 BoringSSL 作为 TLS 后端HTTP/2 开箱可用TLSv1.3 自 Android 10API level 29起可用。Android 端使用独立的平台实现见 okhttp/src/androidMain 下的平台代码与 JVM 的PlatformRegistry逻辑无关。3. GraalVMGraalVM 由 OpenJDK 驱动HTTP/2 可用。文档特别注明官方只以 JDK 11 目标进行过主动测试不支持 JDK 8 target。从 GraalSvm.kt 的 Native Image 配置可以看出其特殊处理在 GraalVM 原生镜像中BouncyCastlePlatform、ConscryptPlatform、Jdk8WithJettyBootPlatform、OpenJSSEPlatform全部被Delete剔除findPlatform()被替换为固定返回Jdk9PlatformTargetClass(Platform.Companion::class) class TargetPlatform { Substitute fun findPlatform(): Platform Jdk9Platform.buildIfSupported()!! }也就是说在 GraalVM Native Image 场景下第三方 Provider 平台类会被整体移除统一走 JDK9 平台路径这是本文表中 GraalVM 行「仅 JDK 11 主动测试」的深层原因之一。4. Bouncy Castle依赖org.bouncycastle:bctls-jdk15on需在 classpath 上见 BouncyCastlePlatform.kt 注释。HTTP/2 可用通过其 JSSE 实现的 ALPN但 TLSv1.3 列为空。实现要点内部创建BouncyCastleJsseProvidernewSSLContext()以SSLContext.getInstance(TLS, provider)获取上下文ALPN 通过BCSSLSocket.parameters.applicationProtocols配置platformTrustManager()使用PKIX算法 BouncyCastleJsseProvider.PROVIDER_NAME。已知限制trustManager(sslSocketFactory)直接抛出UnsupportedOperationException即使用clientBuilder.sslSocketFactory(SSLSocketFactory)自定义工厂与 Bouncy Castle 不兼容同时官方挂有 [bug5698] 跟踪问题。测试佐证BouncyCastleTest.kt 在assumeBouncyCastle()前置条件下验证真实网络请求可达 HTTP/2 与 TLSv1.3。5. Conscrypt首推的 JVM 加速引擎依赖org.conscrypt:conscrypt-openjdk-uber 2.1.0见 ConscryptPlatform.kt 注释。能力HTTP/2 与 TLSv1.3 双 ✅底层是 BoringSSLAndroid 同源因此在 JVM 上能获得与 Android 一致的 TLS 栈体验。激活条件isSupported要求Conscrypt.isAvailable()且版本 2.1.0atLeastVersion(2, 1, 0)并额外做Class.forName(org.conscrypt.Conscrypt$Version)提前抛异常而非致命错误且必须注册为第一个Provider。实现要点newSSLContext()用 Conscrypt 的 Provider 获取TLS上下文版本 API 1.4.0 时默认支持 TLSv1.3configureTlsExtensions()中开启 session ticketsConscrypt.setUseSessionTickets并设置 ALPN 协议列表信任管理器上挂一个DisabledHostnameVerifier因为主机名校验由 OkHttp 自己负责。测试佐证ConscryptTest.kt 验证Platform.get().platformTrustManager()确为 Conscrypt 实例并覆盖atLeastVersion版本比较逻辑。6. OpenJSSE依赖org.openjsse:openjsse 1.1.0。能力TLSv1.3 ✅、HTTP/2 列为空它是 OpenJDK TLS 实现的后向移植backport适合在旧 JDK 上提前获得 TLSv1.3。实现要点OpenJSSEPlatform.ktnewSSLContext()直接请求TLSv1.3上下文——注释说明这是为了「对目标版本范围更明确因为不同 VM 在支持与默认启用的 TLS 版本上常有差异」ALPN 通过org.openjsse.javax.net.ssl.SSLParameters.applicationProtocols设置。同样限制trustManager(sslSocketFactory)抛出UnsupportedOperationException。测试佐证OpenJSSETest.kt 用 MockWebServer 验证 TLSv1.3 握手成功、协议为 HTTP/2且底层 socket 确为org.openjsse.sun.security.ssl.SSLSocketImpl。7. CorrettoAmazon Corretto Crypto Provider能力HTTP/2 与 TLSv1.3 双 ✅底层 OpenSSL官方定位为高性能加密 Provider。文档标注了 [bug5592] 跟踪问题提示其在 OkHttp 集成中存在已知缺陷需要关注。测试佐证CorrettoTest.kt 通过PlatformRule.isCorrettoSupported/isCorrettoInstalled断言其可用性并验证真实网络请求得到 HTTP/2 与 TLSv1.3。四、如何配置把 Provider 注册到首位由于 OkHttp 只看Security.getProviders()[0]正确接入第三方 Provider 的步骤是以 Conscrypt 为例import org.conscrypt.Conscrypt; import java.security.Security; // 必须在创建 OkHttpClient 之前执行 Security.insertProviderAt(Conscrypt.newProvider(), 1); OkHttpClient client new OkHttpClient();insertProviderAt(provider, 1)中的1表示插入到索引 1索引 0 是第一个位置使Security.getProviders()[0]变为目标 Provider同理Bouncy Castle 需要把BouncyCastleProviderJCE 部分名字为BC与BouncyCastleJsseProviderJSSE 部分注册好其中 JSSE Provider 名需为BC以命中isBouncyCastlePreferred判断OpenJSSE 则注册new OpenJSSE()到首位。仓库自带的测试基建演示了这套配置的自动化形式PlatformRule.kt 内部通过Security.insertProviderAt(provider, 1)插入 Conscrypt / OpenJSSE / BouncyCastle并通过Security.insertProviderAt(BouncyCastleProvider(), 1)Security.insertProviderAt(BouncyCastleJsseProvider(), 2)处理 BC 的两段注册还提供了assumeConscrypt()、assumeOpenJSSE()、assumeCorretto()、assumeBouncyCastle()等前置条件与expectFailureOnConscryptPlatform()等失败预期工具方便 CI 在多平台矩阵上跑同一套测试。配置完成后验证当前生效平台的方式检查Platform.get()返回的实例类型如ConscryptPlatform、OpenJSSEPlatform、Jdk9Platform或在握手后读取response.handshake?.tlsVersion与response.protocol确认 TLSv1.3 / HTTP/2 是否按预期协商。五、边界与限制原文 Notes 的展开版本门槛JVM 的 HTTP/2 依赖 Java 9 的 ALPN 支持、TLSv1.3 依赖 Java 11若跑在 JDK 8 早期版本无 ALPNJdk8WithJettyBootPlatform是最后的兼容路径。想提前在旧平台获得新能力应选用 ConscryptHTTP/2 TLSv1.3或 OpenJSSETLSv1.3 backport。Bouncy Castle 的兼容性代价其sslSocketFactory(SSLSocketFactory)自定义工厂不被支持且 BouncyCastle 测试基建中注释提到 ECDSA 密钥场景下该 Provider 存在工作异常测试会退化为 RSA 证书见 PlatformRule.kt 中localhostHandshakeCertificatesWithRsa2048相关逻辑。GraalVM 特例Native Image 下第三方平台类被删除只走Jdk9Platform且官方仅以 JDK 11 目标测试使用 GraalVM 时请锁定 JDK 11 系环境。Corretto 与 Bouncy Castle 的已知缺陷官方分别以 [bug5592] 与 [bug5698] 跟踪接入前应关注对应 issue 状态。Android 无需干预Android 默认栈BoringSSL已覆盖 HTTP/2 与 Android 10 的 TLSv1.3一般不需要额外注册 Provider。六、延伸阅读官方安全总览与支持版本策略security.md版本支持矩阵、漏洞报告与制品签名验证方式TLS 配置历史与演进tls_configuration_history.mdHTTPS 与证书校验指南https.md平台探测源码PlatformRegistry.kt 及各*Platform.kt实现多平台测试基建PlatformRule.kt 与 ConscryptTest.kt、OpenJSSETest.kt、CorrettoTest.kt、BouncyCastleTest.ktGraalVM 原生镜像适配GraalSvm.kt【免费下载链接】okhttpA meticulous HTTP client for the JVM, Android, and GraalVM.项目地址: https://gitcode.com/gh_mirrors/okh/okhttp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进