阿卡版本:
- 阿卡2.4.7 https://github.com/akka/akka/tree/v2.4.7
阿卡特点:
Language: Scala
我正在使用 Akka 2.4.7 的 Http Server 功能来提供几个HTTPS不同端口上的服务连接。
在此阶段,要求 Actor 系统的该组件在一个 JVM 中托管多个 HTTPS 服务 - 它是连接和集成其他服务的后端。
Question:
我想使用Typesafe 的 ssl 配置 http://typesafehub.github.io/ssl-config用于配置每个 HTTPS 服务器的库。我该怎么做呢(我的尝试没有成功)?
我尝试过的:
对于每个服务,我在 application.conf 中定义了 ssl-config 配置块。下一个配置的示例是:
my-service {
ssl-config = {
debug {
all = true
}
sslParameters {
clientAuth : "none"
}
ssl = {
keyManager = {
stores = [
{path: tmp/certs/autumn/devhost.jks, password: "not-real-password", type: "JKS"}
]
}
}
}
}
我使用 HOCON 路径获取这部分配置我的服务定义于应用程序配置文件并将其与参考默认配置合并以创建 SSLConfigSettings。
def parseSslConfig(config: Config): SSLConfigSettings = {
val cfg = config.withFallback(ConfigFactory.defaultReference().getConfig("ssl-config"))
val parser = new SSLConfigParser(EnrichedConfig(cfg), getClass.getClassLoader)
parser.parse()
}
现在有了 SSLConfigSettings 我现在可以创建一个AkkaSSL配置对象,反过来,阿卡2.4.7,可用于创建HttpsConnectionContext https://github.com/akka/akka/blob/4acc1cca6a27be0ff80f801de3640f91343dce94/akka-http-core/src/main/scala/akka/http/scaladsl/ConnectionContext.scala使用函数原型:
//#https-上下文-创建
// 连接上下文
定义 https(
sslContext:SSLContext,
sslConfig:选项[AkkaSSLConfig] =无,
enabledCipherSuites: 选项[immutable.Seq[String]] = None,
enabledProtocols: 选项[immutable.Seq[String]] = None,
clientAuth: 选项[TLSClientAuth] = 无,
ssl参数:选项[SSL参数] = 无)=
新的 HttpsConnectionContext(sslContext、sslConfig、enabledCipherSuites、enabledProtocols、clientAuth、sslParameters)
//#https-上下文-创建
因此,我可以使用如下代码启动 HTTPS 服务器(注意:请求处理程序在其他地方定义,提供Future[HttpResponse]
)
val akkaSSLConfig: AkkaSSLConfig = AkkaSSLConfig().withSettings(sslConfigSettings)
val serverConnectionContext = ConnectionContext.https(SSLContext.getDefault, Some(akkaSSLConfig))
val httpServer = httpServerSystem.bind(interface = "127.0.0.1",
port = 8991,
connectionContext = serverConnectionContext)
val bindingFuture: Future[Http.ServerBinding] = httpServer.to(Sink.foreach {
connection =>
system.log.info(s"Accepted HTTP connection " +
s"[Local: address=${connection.localAddress.getAddress.getHostAddress}, port=${connection.localAddress.getPort};" +
s" Remote: address=${connection.remoteAddress.getAddress.getHostAddress} port=${connection.remoteAddress.getPort}]" + connection.remoteAddress)
connection.handleWithAsyncHandler(httpRequest => requestHandler(httpRequest, connection.localAddress, connection.remoteAddress))
}).run()
服务器启动无异常或错误并绑定到127.0.0.1在定义的端口上8991.
2016-06-11 14:07:51,403 DEBUG [autumn-backend-akka.actor.default-dispatcher-7] TcpListener - Successfully bound to /127.0.0.1:8991
2016-06-11 14:07:51,404 DEBUG [autumn-backend-akka.actor.default-dispatcher-7] TcpListener - started (akka.io.TcpListener@3d1d819f)
2016-06-11 14:07:51,404 DEBUG [autumn-backend-akka.actor.default-dispatcher-7] TcpListener - now watched by Actor[akka://autumn-backend/system/IO-TCP/selectors/$a#-745039521]
2016-06-11 14:07:51,407 DEBUG [autumn-backend-akka.actor.default-dispatcher-5] TcpListener - now watched by Actor[akka://autumn-backend/user/StreamSupervisor-0/$$a#-672917867]
我使用浏览器或者curl访问服务器,结果不好。它要求提供客户端证书,我知道这是错误的,因为我已在 ssl-conf 中明确配置不需要它们,并且 JDK8 中的 ssl-conf 默认情况下将其设置为不需要。
curl -v https://localhost:8991
* Rebuilt URL to: https://localhost:8991/
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8991 (#0)
* SSL peer handshake failed, the server most likely requires a client certificate to connect
* Closing connection 0
curl: (35) SSL peer handshake failed, the server most likely requires a client certificate to connect
进一步调查opensslwith _s_client_ 选项显示没有发生 SSL 握手,也没有返回证书,尽管知道密钥库很好并且可以在其他地方使用。
openssl s_client -showcerts -connect localhost:8991
CONNECTED(00000003)
140735299473488:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:769:
---
no peer certificate available
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 317 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
---
调试模式下的 Akka 日志没有显示异常,并且已建立 TCP 连接,TLS actor 启动然后立即停止。
2016-06-11 14:09:26,378 DEBUG [autumn-backend-akka.actor.default-dispatcher-6] TcpListener - New connection accepted
2016-06-11 14:09:26,378 DEBUG [autumn-backend-akka.actor.default-dispatcher-9] SelectionHandler - now supervising Actor[akka://autumn-backend/system/IO-TCP/selectors/$a/9#1252313265]
2016-06-11 14:09:26,378 DEBUG [autumn-backend-akka.actor.default-dispatcher-5] TcpIncomingConnection - started (akka.io.TcpIncomingConnection@6f12f120)
2016-06-11 14:09:26,378 DEBUG [autumn-backend-akka.actor.default-dispatcher-5] TcpIncomingConnection - now watched by Actor[akka://autumn-backend/system/IO-TCP/selectors/$a#-745039521]
2016-06-11 14:09:26,381 INFO [autumn-backend-akka.actor.default-dispatcher-7] ActorSystemImpl - Accepted HTTP connection [Local: address=127.0.0.1, port=8991; Remote: address=127.0.0.1 port=58726]/127.0.0.1:58726
2016-06-11 14:09:26,384 DEBUG [autumn-backend-akka.actor.default-dispatcher-9] StreamSupervisor - now supervising Actor[akka://autumn-backend/user/StreamSupervisor-0/flow-9-0-unknown-operation#149184815]
2016-06-11 14:09:26,385 DEBUG [autumn-backend-akka.actor.default-dispatcher-7] TcpIncomingConnection - now watched by Actor[akka://autumn-backend/user/StreamSupervisor-0/$$j#-1999211380]
2016-06-11 14:09:26,385 DEBUG [autumn-backend-akka.actor.default-dispatcher-9] ActorGraphInterpreter - started (akka.stream.impl.fusing.ActorGraphInterpreter@57451dc8)
2016-06-11 14:09:26,385 DEBUG [autumn-backend-akka.actor.default-dispatcher-5] StreamSupervisor - now supervising Actor[akka://autumn-backend/user/StreamSupervisor-0/flow-9-1-unknown-operation#1511230856]
sslConfig.config.loose.disableSNI = false
2016-06-11 14:09:26,387 DEBUG [autumn-backend-akka.actor.default-dispatcher-5] TLSActor - started (akka.stream.impl.io.TLSActor@50f220e8)
2016-06-11 14:09:26,389 DEBUG [autumn-backend-akka.actor.default-dispatcher-5] TLSActor - stopped
运行时调试显示正在获取密钥库:
akkaSSLConfig = {com.typesafe.sslconfig.akka.AkkaSSLConfig@7851}
system = {akka.actor.ActorSystemImpl@7850} "akka://autumn-backend"
config = {com.typesafe.sslconfig.ssl.SSLConfigSettings@7849} "SSLConfig(None,SSLDebugConfig(false,false,false,None,false,false,false,false,None,false,false,false,false,false),false,Vector(RSA keySize < 2048, DSA keySize < 2048, EC keySize < 224),Vector(MD2, MD4, MD5),None,Some(Vector(TLSv1.2, TLSv1.1, TLSv1)),class com.typesafe.sslconfig.ssl.DefaultHostnameVerifier,KeyManagerConfig(SunX509,List(KeyStoreConfig(None,Some(config/certs/autumn/devhost.jks),Some(A8C7B78Ymb),JKS))),SSLLooseConfig(false,None,None,false,false,false,false),TLSv1.2,None,None,SSLParametersConfig(Default,Vector()),TrustManagerConfig(PKIX,List()))"
default = false
protocol = "TLSv1.2"
checkRevocation = {scala.None$@7905} "None"
revocationLists = {scala.None$@7905} "None"
enabledCipherSuites = {scala.None$@7905} "None"
enabledProtocols = {scala.Some@7906} "Some(Vector(TLSv1.2, TLSv1.1, TLSv1))"
disabledSignatureAlgorithms = {scala.collection.immutable.Vector@7907} "Vector" size = 3
disabledKeyAlgorithms = {scala.collection.immutable.Vector@7911} "Vector" size = 3
sslParametersConfig = {com.typesafe.sslconfig.ssl.SSLParametersConfig@7917} "SSLParametersConfig(Default,Vector())"
keyManagerConfig = {com.typesafe.sslconfig.ssl.KeyManagerConfig@7918} "KeyManagerConfig(SunX509,List(KeyStoreConfig(None,Some(config/certs/autumn/devhost.jks),Some(A8C7B78Ymb),JKS)))"
algorithm = "SunX509"
keyStoreConfigs = {scala.collection.immutable.$colon$colon@7942} "::" size = 1
0 = {com.typesafe.sslconfig.ssl.KeyStoreConfig@9390} "KeyStoreConfig(None,Some(config/certs/autumn/devhost.jks),Some(not-real-password),JKS)"
有效的是,如果我手动创建 HttpsConnectionContext 并且不使用 ssl-conf 或 AkkaSSLConfig - 但这不是目标。如何使用 AkkaSSLconf 对象和 Typesafe ssl-config 库配置和创建 HTTPS 配置连接?
更新1:
如果我特别要求TLSTLS 上下文的实例如下:
val sslCtx = SSLContext.getInstance("TLS")
我收到一个异常,即 sslContext 未初始化。但要init
SSLContext,我需要创建密钥库、信任库,这一切都很好,但感觉我忽略了 ssl-conf 库的所有优点,该库已经定义了所有这些东西。
更新2:
我发现可以使用以下方法创建 HTTPS 连接上下文:
Http().createServerHttpsContext(akkaSSLConfig)
您可以使用 AkkaSSLConfig 创建 HTTPS 服务器上下文,这是我所追求的好东西。问题是测试 HTTPS 服务器不起作用,它只是挂起 1 分钟,但有例外:
2016-06-12 11:14:53,222 DEBUG [autumn-backend-akka.actor.default-dispatcher-12] RepointableActorRef - Aborting tcp connection because of upstream failure: No elements passed in the last 1 minute.
akka.stream.impl.Timers$IdleTimeoutBidi$$anon$7.onTimer(Timers.scala:160)
akka.stream.stage.TimerGraphStageLogic.akka$stream$stage$TimerGraphStageLogic$$onInternalTimer(GraphStage.scala:1125)
akka.stream.stage.TimerGraphStageLogic$$anonfun$akka$stream$stage$TimerGraphStageLogic$$getTimerAsyncCallback$1.apply(GraphStage.scala:1114)
akka.stream.stage.TimerGraphStageLogic$$anonfun$akka$stream$stage$TimerGraphStageLogic$$getTimerAsyncCallback$1.apply(GraphStage.scala:1114)
akka.stream.impl.fusing.GraphInterpreter.runAsyncInput(GraphInterpreter.scala:572)
akka.stream.impl.fusing.GraphInterpreterShell.receive(ActorGraphInterpreter.scala:420)
akka.stream.impl.fusing.ActorGraphInterpreter.akka$stream$impl$fusing$ActorGraphInterpreter$$processEvent(ActorGraphInterpreter.scala:604)
akka.stream.impl.fusing.ActorGraphInterpreter$$anonfun$receive$1.applyOrElse(ActorGraphInterpreter.scala:619)
akka.actor.Actor$class.aroundReceive(Actor.scala:484)
我在 GitHub 上的 Akka 存储库上查看了 createServerHttpsContext 的源代码here https://github.com/akka/akka/blob/4acc1cca6a27be0ff80f801de3640f91343dce94/akka-http-core/src/main/scala/akka/http/scaladsl/Http.scala并发现:
// currently the same configuration as client by default, however we should tune this for server-side apropriately (!)
def createServerHttpsContext(sslConfig: AkkaSSLConfig): HttpsConnectionContext = {
log.warning("Automatic server-side configuration is not supported yet, will attempt to use client-side settings. " +
"Instead it is recommended to construct the Servers HttpsConnectionContext manually (via SSLContext).")
createClientHttpsContext(sslConfig)
}
为什么 HTTPS 服务器不能与createServerHttpsContext(..)
?特别是考虑到您基本上手动设置了 TLS SSLContext、KeyManagerFactory(有钥匙商店),SecureRandom 的一个实例就可以了。