如何使用Akka和SSL证书发送HTTP请求

6

我在配置Akka HTTP时遇到了一些麻烦,希望能够使用特定的SSL证书从Scala发出HTTP请求。我可以轻松地进行非SSL基础请求,但似乎找不到正确的配置Akka以使用一组证书的示例。

不幸的是,Akka HTTP网站上的文档提供了有关服务器端SSL配置的详细信息,但没有给出有关客户端配置的具体示例。

如果有这样使用的任何示例,将不胜感激。


在2018年有相同的需求。你解决了吗? - akauppi
你能检查一下这个链接吗 https://gist.github.com/iRevive/4a3c7cb96374da5da80d4538f3da17cb 。 - Guda uma shanker
1个回答

1

我在我的小项目中做过这个,我认为即使问题已经老旧,它对于某些人可能仍然有用。您将需要创建您的keystore.pkcs12文件。我使用的build.sbt是:

val akkaVersion = "2.6.10"
 val akkaHttpVersion = "10.2.2"
  "com.typesafe.akka" %% "akka-actor" % akkaVersion,
  "com.typesafe.akka" %% "akka-http" % akkaHttpVersion,
  "com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion,
  "com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion,
  "com.typesafe.akka" %% "akka-http2-support" % akkaHttpVersion

我拥有一个名为HttpsServerContext的对象,我可以在我的项目中的任何Akka-http api中使用它。我通过调用enableHttps(HttpsServerContext.httpsConnectionContext)来使用它。
object HttpsServerContext {
  // Step 1 - key store
  val ks: KeyStore = KeyStore.getInstance("PKCS12")
  val keystoreFile: InputStream = getClass.getClassLoader.getResourceAsStream("certs/keystore.pkcs12")
  // alternative: new FileInputStream(new File("src/main/resources/certs/keystore.pkcs12"))
  val password = "akka-https".toCharArray // TODO: fetch the password from a secure place
  ks.load(keystoreFile, password)

  // Step 2 - initialize a key manager
  val keyManagerFactory = KeyManagerFactory.getInstance("SunX509") // PKI public key infrastructure
  keyManagerFactory.init(ks, password)

  // Step 3 - initialize a trust manager
  val trustmanagerFactory = TrustManagerFactory.getInstance("SunX509")
  trustmanagerFactory.init(ks)

  // Step 4 - initialize a SSL context
  val sslContext: SSLContext = SSLContext.getInstance("TLS")
  sslContext.init(keyManagerFactory.getKeyManagers, trustmanagerFactory.getTrustManagers, new SecureRandom())

  // Step 5 - return the HTTPS connection context
  val httpsConnectionContext: HttpsConnectionContext = ConnectionContext.httpsServer(sslContext)
}

然后我有一个异步请求处理程序。
implicit val system = ActorSystem("HttpsRestApi")

import system.dispatcher
    val asyncRequestHandler: HttpRequest => Future[HttpResponse] = {
      case HttpRequest(HttpMethods.GET, Uri.Path("/home"), headers, entity, protocol) =>
        Future(HttpResponse(
          StatusCodes.OK, // HTTP 200
          entity = HttpEntity(
            ContentTypes.`text/html(UTF-8)`,
            """
              |<html>
              | <body>
              |  Async Hello Akka HTTPS
              | </body>
              |</html>
              |""".stripMargin)
        ))
      case HttpRequest(HttpMethods.GET, Uri.Path("/redirect"), headers, entity, protocol) =>
        Future(HttpResponse(
          StatusCodes.Found,
          headers = List(Location("http://www.google.com"))
        ))
      case request: HttpRequest =>
        request.discardEntityBytes()
        Future(HttpResponse(
          StatusCodes.NotFound, // HTTP 404
          entity = HttpEntity(
            ContentTypes.`text/html(UTF-8)`,
            """
              |<html>
              | <body>
              |  OOPS! async page not found =(<br>try https://localhost:8553/home
              | </body>
              |</html>
              |""".stripMargin)
        ))
    }
    val httpsBindingAsync = Http()
      .newServerAt("localhost", 8443)
      .enableHttps(HttpsServerContext.httpsConnectionContext)
      .bind(asyncRequestHandler)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接