带有 ssl-conf 的 Akka HTTPS (SSL) 服务器

2023-12-27

阿卡版本:

  • 阿卡2.4.7 https://github.com/akka/akka/tree/v2.4.7

阿卡特点:

  • HTTPS服务器 支持 http://doc.akka.io/docs/akka/2.4.7/scala/http/server-side-https-support.html

  • Typesafe 的 ssl 配置 http://typesafehub.github.io/ssl-config

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 未初始化。但要initSSLContext,我需要创建密钥库、信任库,这一切都很好,但感觉我忽略了 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 的一个实例就可以了。


正如其他评论中所发布的,存在一个 git hub 问题,指出尚不支持“自动”使用配置。不过,这个问题现在已经结束了;刚刚未完成moved https://github.com/akka/akka-http/issues/55。我浏览了未来版本的发行说明,但没有看到任何与此相关的内容。现在对安全性如此重视,令我惊讶的是 SSL/TSL 的设置并不是开箱即用的。

我正在使用 v2.4.4 (当前是 2.4.16)并且与提问者类似,我发现虽然 akk-http 文档告诉你使用配置,但实际上从调试中你可以看到配置得到读入后,实际使用它的实现尚未完成。我在日志中收到此消息:

akka.actor.ActorSystemImpl(OtisRestActorSystem)] 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)

我尝试使用他们的 ssl 配置“手动构建服务器 HttpsConnectionContext”,但我无法让它工作。

当我最初进行故障排除时,还有其他消息显示它在配置的密钥存储中读取(它不使用类路径来查找它,因此一开始找不到它)。所以我不确定哪些部分正在工作,哪些部分丢失了。所以我最终完全放弃了 akka-http ssl 配置并自己设置它,因为我的用例非常简单。我只想启用服务器端 SSL/TSL。

在我的配置中,我有:

  ssl {
    keyStoreFileName = "myKeyFile.p12"
    keyStorePassword = "myPassword"
  }

为了阅读我的设置,我有:

class Settings(config: Config) extends Extension {
  object Ssl {
    var KeyStoreFileName = config.getString("ssl.keyStoreFileName")
    var KeyStorePassword = config.getString("ssl.keyStorePassword")
  }
}

对于“应用程序”我有:

object RestWebServiceApp extends App with RouteConcatenation {
  import akka.event.{Logging, LoggingAdapter}
  import akka.http.scaladsl.{ ConnectionContext, HttpsConnectionContext, Http }
  import akka.http.scaladsl.server.Directives._
  import akka.http.scaladsl.model.MediaTypes._
  import akka.stream.{ActorMaterializer, ActorMaterializerSettings}
  import java.io.InputStream
  import java.security.{ SecureRandom, KeyStore }
  import javax.net.ssl.{ SSLContext, TrustManagerFactory, KeyManagerFactory }
  import JsonSupport._

  implicit val system = ActorSystem("OtisRestActorSystem")
  implicit val materializer: ActorMaterializer = ActorMaterializer(ActorMaterializerSettings(system))
  implicit val ec = system.dispatcher

  ...  //setting up all the routes, etc.

  val settings = Settings(system)
  val fileName = settings.Ssl.KeyStoreFileName
  val keyFile: InputStream = getClass.getClassLoader.getResourceAsStream(fileName)
  require(keyFile != null, s"Failed to load key file: ${settings.Ssl.KeyStoreFileName}")
  val extension = if(fileName.lastIndexOf('.')>0) fileName.substring(fileName.lastIndexOf('.')+1) else ""
  val keyStore: KeyStore = extension.toLowerCase match {
    case "jks" =>  KeyStore.getInstance("jks") //Java Key Store; Java default and only works with Java; tested
    case "jcek" =>  KeyStore.getInstance("JCEKS") //Java Cryptography Extension KeyStore; Java 1.4+; not tested
    case "pfx" | "p12" =>  KeyStore.getInstance("PKCS12") // PKCS #12, Common and supported by many languages/frameworks; tested
    case _ => throw new IllegalArgumentException(s"Key has an unknown type extension $extension. Support types are jks, jcek, pfx, p12.")
  }
  val password: Array[Char] = (if(settings.Ssl.KeyStorePassword==null) "" else settings.Ssl.KeyStorePassword).toCharArray
  keyStore.load(keyFile, password)

  //TODO: looks like the "SunX509", "TLS", are defined in the keystore, should we pull them out rather than hard coding?
  val keyManagerFactory: KeyManagerFactory = KeyManagerFactory.getInstance("SunX509")
  keyManagerFactory.init(keyStore, password)

  val tmf: TrustManagerFactory = TrustManagerFactory.getInstance("SunX509")
  tmf.init(keyStore)

  val sslContext: SSLContext = SSLContext.getInstance("TLS")
  sslContext.init(keyManagerFactory.getKeyManagers, tmf.getTrustManagers, new SecureRandom)
  val https: HttpsConnectionContext = ConnectionContext.https(sslContext)
  Http().setDefaultServerHttpContext(https)
  Http().bindAndHandle(routes, "localhost", 433, connectionContext = https)
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带有 ssl-conf 的 Akka HTTPS (SSL) 服务器 的相关文章

随机推荐

  • 为 Laravel Blade 模板解析字符串而不是文件

    我需要缓存 CMS 生成的远程刀片模板 以使应用程序的公共接口保持最新 理想情况下 我可以使用 file get contents 和缓存每周检查一次更新 有没有办法让 Laravel 使用变量的内容而不是文件作为刀片模板 我找不到让 La
  • Pylance 不允许我导航到源代码,而是将我带到 .pyi 存根

    我正在使用 pylance 作为 vs code 它工作得非常好 除了因为我使用它 当我尝试从已安装的库检查代码时 我只能得到存根 我认为是由 pylance 生成的 For example the information shown ab
  • 有没有办法获取unix套接字连接另一端的uid

    有没有办法让 UNIX 域套接字侦听器仅接受来自特定用户的连接 chmod chown不适用于抽象套接字 afaik 或者换句话说 获取传入连接的 uid 在 Linux 上 Dbus 在Linux上使用抽象unix socket 有一个功
  • 如何在数组中搜索子字符串匹配项?

    我需要在 JavaScript 中搜索数组 搜索将仅匹配字符串的一部分 因为字符串将包含其他组件 然后我需要返回成功匹配的数组元素和完整字符串 Example const windowArray item thing id 3 text c
  • Android Seekbar - 只允许用拇指进行更改?

    我有一个搜索栏 我只想允许用拇指 手柄部分进行更改 如果用户点击其他任何地方 我希望忽略该点击 是否有固有的属性可以做到这一点 如果没有 我已经知道我可以设置一个 onTouch 监听器并返回true 禁用 它 但是有没有办法检测拇指何时被
  • 打字稿和 d3

    我有一个使用 d3 库的应用程序 在打字稿代码中 为了成功使用 d3 即 没有编译器错误 TS2686 d3 引用 UMD 全局 但当前文件是模块 我必须包含以下行 import as d3 from d3 问题是它会发出 require
  • QT,如何聚焦虚拟键盘,并使用键盘控制虚拟键盘

    我在嵌入式设备上使用Qt5的虚拟键盘 没有鼠标 键盘不是完整的PC键盘 而是只有十一个键 包括上 下 左 右 enter esc 所以我想专注于虚拟键盘 并使用上 下 左 右 回车来控制虚拟键盘 模拟鼠标点击虚拟键 怎么做 doc qt i
  • 如何使用 winmerge 行过滤器忽略包含特定单词的行?

    我有许多文件包含以下类型的行 version Revision 1 xxx 我希望在使用 winmerge 进行比较时忽略这种类型的行 我尝试过使用线路滤波器 但是 直到无法做到这一点 有人可以在这方面帮助我吗 你实际上可以这样做线路滤波器
  • 如何获取 Facebook 用户的信息并将其插入数据库?

    我不知道如何问它 但我正在尝试自学如何创建一个使用图形 api 的程序 我见过的大多数教程都是较旧的 我不知道它们现在有多相关 本质上 我试图获取有人点击我的应用程序的 东西 它说 这个应用程序需要您的用户名等 然后允许或不允许 我希望它获
  • 在组合键中使用 JPA AttributeConverter 时,Spring-data/hibernate 查询中不支持 JPA AttributeConverter

    这是我的枚举 public enum FooBarType Foo Bar javax persistence Converter public static class Converter implements AttributeConv
  • java / Android 一个进度条下载多个文件

    我在 for 循环的帮助下在 AsyncTask 中下载多个文件 下面的代码工作正常 但下载的每个文件都有自己的单个进度条 我只想为所有下载的文件提供一个进度条 ProgressDialog for downloading images O
  • 在 PowerBI 中使用 ALLEXCEPT 实现分组百分比的问题

    我想获得一个分组百分比作为新列或新度量 这是我在论坛中读到的内容推荐的 我有一个数据 用户将使用切片器来获取各种百分比 然而 目前我的查询一直失败 我访问过论坛 但似乎不知道如何分组并获取组的百分比 此外 我无法使用查询编辑器中的分组依据工
  • 以 JSON 格式将数据从 Kafka Topic 推送到 PostgreSQL

    更新后出错 2019 07 29 12 52 23 301 INFO Initializing writer using SQL dialect PostgreSqlDatabaseDialect io confluent connect
  • Joomla 如何自定义主菜单

    我正在学习 joomla 并面临下一个问题 这是 HTML 格式的主菜单 ul li class active a href home a li li a href bio a li li a href news a li li a hre
  • 反向特征查找?

    我一直在寻找解决以下问题的设计 需要几句话来描述 我们有四种类型 A1 A2 B 和 C 我们想编写一个函数 fn 它以类型 P 作为参数 使用特征 P 在 A1 A2 B C 内解析为 PA1 PA2 PB PC fn 的实现对于 PA1
  • 如何计算硬币问题的可能组合

    我正在尝试实现一个硬币问题 问题规范是这样的 创建一个函数来计算可用于给定金额的所有可能的硬币组合 All possible combinations for given amount 15 coin types 1 6 7 1 1 1 1
  • TEdgeBrowser 弹出菜单/上下文菜单

    如何覆盖 TEdgebrowser 组件中的上下文菜单 财产检查员不为此提供活动 可以使用 Javascript 停用上下文菜单 该解决方案并未涵盖所有用例 对于我的问题来说已经足够了
  • ActiveSupport::Deprecation.silenced = true 对我不起作用?

    我的应用程序是使用 Ruby 1 8 7 和 Rails 2 3 11 开发的 我在运行 rake spec 时收到很多弃用警告 DEPRECATION WARNING ActiveSupport Dependencies load pat
  • .Net 4 中巨大的性能差异背后的原因是什么

    我只是在对红黑树进行一些研究 我知道 Net 4 0 中的 SortedSet 类使用 RedBlack 树 因此 我使用 Reflector 取出该部分并创建了一个 RedBlackTree 类 现在我正在这个 RedBlackTree
  • 带有 ssl-conf 的 Akka HTTPS (SSL) 服务器

    阿卡版本 阿卡2 4 7 https github com akka akka tree v2 4 7 阿卡特点 HTTPS服务器 支持 http doc akka io docs akka 2 4 7 scala http server