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

Scala/Akka HTTP实现curl --cacert HTTPS请求报错问题咨询

问题根因

报错核心是Akka HTTP的SSL上下文类型传错:
你调用客户端发请求的singleRequest方法时,第二个参数要求传入客户端侧的HTTPS连接上下文,但你实际传入的是为服务端监听配置的服务端SSL上下文。Akka流的TLS层初始化时,识别到传入的是服务端上下文,会判定当前场景是绑定端口监听入站连接,不应该携带目标服务的host/port参数,和你发请求时传入的目标地址参数冲突,直接抛出Actor初始化异常。

另外你贴的代码还有两个会导致后续请求失败的隐藏问题:

  • 你写的HttpsServerContext里生成的自定义CA信任的SSLContext根本没有被传入请求方法,实际传的是名为getSslContextForNoCertificateCheck的上下文——从命名看这是跳过所有证书校验的配置,完全不符合你用指定CA做服务端校验的需求
  • Authorization请求头格式错误,Bearer和token内容之间缺少必填空格,就算SSL连接成功,也会因为鉴权头格式非法被服务端拒绝。
修复方案

按以下步骤调整即可:

  1. 基于自定义CA证书生成客户端专用的HTTPS连接上下文,注意用Akka提供的httpsClient方法包装,不要生成服务端类型的上下文,参考实现:
import akka.http.scaladsl.{ConnectionContext, HttpsConnectionContext}
import java.io.FileInputStream
import java.security.cert.X509Certificate
import java.security.{KeyStore, SecureRandom}
import javax.net.ssl.{CertificateFactory, SSLContext, TrustManagerFactory}

// 加载指定CA证书
val certInputStream = new FileInputStream("cacert.crt")
val certFactory = CertificateFactory.getInstance("X.509")
val customCaCert = certFactory.generateCertificate(certInputStream).asInstanceOf[X509Certificate]
certInputStream.close()

// 构造仅信任该CA的信任库
val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
val trustKeyStore = KeyStore.getInstance(KeyStore.getDefaultType)
trustKeyStore.load(null)
trustKeyStore.setCertificateEntry("custom-trusted-ca", customCaCert)
trustManagerFactory.init(trustKeyStore)

// 初始化客户端SSL上下文,包装为Akka HTTP可识别的客户端连接上下文
val clientSslContext = SSLContext.getInstance("TLS")
clientSslContext.init(null, trustManagerFactory.getTrustManagers, new SecureRandom())
val customHttpsContext: HttpsConnectionContext = ConnectionContext.httpsClient(clientSslContext)
  1. 修正请求逻辑的两处错误:
    • 把singleRequest的第二个参数替换为上面生成的customHttpsContext,移除原来传的跳过证书校验的上下文
    • 修正Authorization头格式,在Bearer后补空格
      修正后的请求代码:
val request = HttpRequest(uri = targetUri)
  .withMethod(HttpMethods.GET)
  // 注意Bearer和token之间必须有空格
  .withHeaders(RawHeader("Authorization", s"Bearer $tokenfileContents"))

val responseFuture = Http().singleRequest(request, customHttpsContext)
  1. 运行前确认cacert.crt的路径是程序运行时可访问的正确路径,避免文件找不到导致的信任库初始化失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 12:21:34