Akka http 信任所有证书
Akka http trust all certs
我只是想跳过证书验证(基本上与 curl --insecure 相同)。
versions
: scala 2.12, akka-http 10.2.4
我试过这些但都没有用:
- https://gist.github.com/iRevive/4a3c7cb96374da5da80d4538f3da17cb
- 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.https
。 initializing the trustfulSslContext earlier 对我有用。
至于您的第二种方法:禁用主机名验证不会禁用“其余”证书验证。 JVM 仍将验证证书是否有效——它只是不再验证它是否属于您正在连接的主机名。要接受无效证书,您必须使用自定义 SSLContext
。您的示例可以是 adapted to do that as well,但在所有其他条件相同的情况下,您的第一种方法更简单,并且不需要在第二种方法中进行额外的间接访问。
我只是想跳过证书验证(基本上与 curl --insecure 相同)。
versions
: scala 2.12, akka-http 10.2.4
我试过这些但都没有用:
- https://gist.github.com/iRevive/4a3c7cb96374da5da80d4538f3da17cb
- 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.https
。 initializing the trustfulSslContext earlier 对我有用。
至于您的第二种方法:禁用主机名验证不会禁用“其余”证书验证。 JVM 仍将验证证书是否有效——它只是不再验证它是否属于您正在连接的主机名。要接受无效证书,您必须使用自定义 SSLContext
。您的示例可以是 adapted to do that as well,但在所有其他条件相同的情况下,您的第一种方法更简单,并且不需要在第二种方法中进行额外的间接访问。