Akka http 信任所有证书

Akka http trust all certs

我只是想跳过证书验证(基本上与 curl --insecure 相同)。

versions: scala 2.12, akka-http 10.2.4

我试过这些但都没有用:

  1. https://gist.github.com/iRevive/4a3c7cb96374da5da80d4538f3da17cb
  2. https://doc.akka.io/docs/akka-http/current/client-side/client-https-support.html#disabling-hostname-verification

自定义 SSLContext

implicit val system: ActorSystem[Nothing] = ActorSystem(Behaviors.empty, "SingleRequest")
implicit val executionContext: ExecutionContextExecutor = system.executionContext
val noCertificateCheckContext = ConnectionContext.https(trustfulSslContext)

private val trustfulSslContext: SSLContext = {

  object NoCheckX509TrustManager extends X509TrustManager {
  override def checkClientTrusted(chain: Array[X509Certificate], authType: String) = ()

  override def checkServerTrusted(chain: Array[X509Certificate], authType: String) = ()

  override def getAcceptedIssuers = Array[X509Certificate]()
  }

  val context = SSLContext.getInstance("TLS")
  context.init(Array[KeyManager](), Array(NoCheckX509TrustManager), null)
  context
}
val res = Await.result(Http().singleRequest(Get(url), noCertificateCheckContext), 60 seconds)

Result:

java.util.concurrent.TimeoutException: Futures timed out after [60 seconds]

按照官方文档:

      implicit val system: ActorSystem[Nothing] = ActorSystem(Behaviors.empty,"SingleRequest")
      implicit val executionContext: ExecutionContextExecutor = system.executionContext
      val noCertificateCheckContext = ConnectionContext.httpsClient(getConnection _)

      def getConnection(host: String, port: Int): SSLEngine  = {
        val engine = SSLContext.getDefault.createSSLEngine(host,port)
        engine.setUseClientMode(true)
        engine
      }
      val res = Http().outgoingConnectionHttps("localhost",4443, connectionContext = noCertificateCheckContext)
      val response = Await.result(Source.single(Get(url)).via(res).runWith(Sink.head), 60 seconds)
      val responseString =Await.result(Unmarshal(response).to[String], 60 seconds)
      println(responseString)

结果:

Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

tried your "Custom SSLContext" reproducer。除了超时,它还在日志记录中产生了以下堆栈跟踪:

Caused by: java.lang.NullPointerException: null
    at akka.stream.scaladsl.TLS$.$anonfun$apply(TLS.scala:92)
    at akka.stream.impl.io.TLSActor.liftedTree1(TLSActor.scala:162)
    at akka.stream.impl.io.TLSActor.<init>(TLSActor.scala:162)
    at akka.stream.impl.io.TLSActor$.$anonfun$props(TLSActor.scala:40)

也许您的类路径中没有 slf4j 记录器?在这种情况下,它应该显示警告。无论如何,在查看代码后,这表明 sslContext 在这里是 null。确实如此:在初始化之前,您已经将 trustfulSslContext 传递给 ConnectionContext.httpsinitializing the trustfulSslContext earlier 对我有用。

至于您的第二种方法:禁用主机名验证不会禁用“其余”证书验证。 JVM 仍将验证证书是否有效——它只是不再验证它是否属于您正在连接的主机名。要接受无效证书,您必须使用自定义 SSLContext。您的示例可以是 adapted to do that as well,但在所有其他条件相同的情况下,您的第一种方法更简单,并且不需要在第二种方法中进行额外的间接访问。