具有自签名证书的Spray https服务器的配置问题? [英] Configuration issue for Spray https server with self-signed certificate?

查看:125
本文介绍了具有自签名证书的Spray https服务器的配置问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Mac 10.9.4上使用Spray 1.3,Akka 2.3和Scala 2.11来设置HTTP服务器.我正在关注Ch. Manning的Akka in Action中的2个示例(示例代码在此处提供: https://github.com /RayRoestenburg/akka-in-action.git ),它可以在使用http时进行编译,运行并按预期方式运行,但是在配置它与https配合使用时遇到了麻烦.

I am using Spray 1.3, Akka 2.3, and Scala 2.11 on Mac 10.9.4 to set up an HTTP server. I am following the Ch. 2 example in Manning's Akka in Action (sample code available here: https://github.com/RayRoestenburg/akka-in-action.git), which compiles, runs, and behaves as expected when I use http, but I am having trouble configuring it for use with https.

要与https一起运行,我生成了一个自签名证书,如下所示:

To run with https, I have generated a self-signed certificate as follows:

keytool -genkey -keyalg RSA -alias selfsigned -keystore myjks.jks -storepass abcdef -validity 360 -keysize 2048

在此示例之后,我添加了一个SSL配置类:

I've added an SSL config class:

package com.goticks

import java.security.{SecureRandom, KeyStore}
import javax.net.ssl.{KeyManagerFactory, SSLContext, TrustManagerFactory}
import spray.io._

// for SSL support (if enabled in application.conf)
trait MySSLConfig {

  // if there is no SSLContext in scope implicitly the HttpServer uses the default SSLContext,
  // since we want non-default settings in this example we make a custom SSLContext available here
  implicit def sslContext: SSLContext = { 
    val keyStoreResource = "myjks.jks"
    val password = "abcdef"

    val keyStore = KeyStore.getInstance("jks")
    keyStore.load(getClass.getResourceAsStream(keyStoreResource), password.toCharArray)
    val keyManagerFactory = KeyManagerFactory.getInstance("SunX509")
    keyManagerFactory.init(keyStore, password.toCharArray)
    val trustManagerFactory = TrustManagerFactory.getInstance("SunX509")
    trustManagerFactory.init(keyStore)
    val context = SSLContext.getInstance("TLS")
    context.init(keyManagerFactory.getKeyManagers, trustManagerFactory.getTrustManagers, new SecureRandom)
    context
  }

  // if there is no ServerSSLEngineProvider in scope implicitly the HttpServer uses the default one,
  // since we want to explicitly enable cipher suites and protocols we make a custom ServerSSLEngineProvider
  // available here
  implicit def sslEngineProvider: ServerSSLEngineProvider = { 
    ServerSSLEngineProvider { engine =>
      engine.setEnabledCipherSuites(Array("TLS_RSA_WITH_AES_256_CBC_SHA"))
      engine.setEnabledProtocols(Array("SSLv3", "TLSv1"))
      engine
    }   
  }
}

我已经更新了Main类以使用SSL配置:

I've updated the Main class to use the SSL config:

package com.goticks

import akka.actor._
import akka.io.IO

import spray.can.Http
import spray.can.server._

import com.typesafe.config.ConfigFactory

object Main extends App with MySSLConfig {
  val config = ConfigFactory.load()
  val host = config.getString("http.host")
  val port = config.getInt("http.port")

  implicit val system = ActorSystem("goticks")

  val api = system.actorOf(Props(new RestInterface()), "httpInterface")
  IO(Http) ! Http.Bind(listener = api, interface = host, port = port)
}

并且我已经更新了application.conf:

and I've updated the application.conf:

spray {
  can {
    server {
      server-header = "GoTicks.com REST API"
      ssl-encryption = on
    }
  }
}

编译并运行服务器后,尝试执行https GET时出现以下错误:

After compiling and running the server, I get the following error when I try to do an https GET:

[ERROR] [09/15/2014 10:40:48.056] [goticks-akka.actor.default-dispatcher-4] [akka://goticks/user/IO-HTTP/listener-0/7] Aborting encrypted connection to localhost/0:0:0:0:0:0:0:1%0:59617 due to [SSLHandshakeException:no cipher suites in common] -> [SSLHandshakeException:no cipher suites in common]

我不确定我的问题是否与生成的密钥或配置有关.顺便说一句,我的最终目标是将此配置与TCP套接字一起使用(请参阅我的其他问题:

I'm not sure if my problem is with the generated key, or with my configuration. Incidentally, my final goal is to use this configuration with a TCP socket (see my other question: TCP socket with SSL on Scala with Akka), but I was unable to find documentation for running secure TCP, so I thought I would start with HTTPS.

感谢您的帮助.

推荐答案

我终于能够使用 Apache Camel 使它正常工作可以在此处找到建议.引入Camel只是为了建立SSLContext似乎有点过头了,但这终于奏效了.

I was finally able to make it work using Apache Camel following the advice found here. Seems like overkill to bring in Camel just to set up the SSLContext, but this is what finally worked.

我的SSLConfig最终看起来像这样:

My SSLConfig ended up looking like this:

import javax.net.ssl.SSLContext
import spray.io._
import org.apache.camel.util.jsse._

trait MySSLConfig {
    implicit def sslContext: SSLContext = {
        //val keyStoreFile = "/Users/eschow/repo/services/jks/keystore.jks"
        val keyStoreFile = "/Users/eschow/code/scala/akka-in-action/chapter2/myjks.jks"

        val ksp = new KeyStoreParameters()
        ksp.setResource(keyStoreFile);
        ksp.setPassword("abcdef")

        val kmp = new KeyManagersParameters()
        kmp.setKeyStore(ksp)
        kmp.setKeyPassword("abcdef")

        val scp = new SSLContextParameters()
        scp.setKeyManagers(kmp)

        val context= scp.createSSLContext()

        context
      }

    implicit def sslEngineProvider: ServerSSLEngineProvider = {
        ServerSSLEngineProvider { engine =>
            engine.setEnabledCipherSuites(Array("TLS_RSA_WITH_AES_256_CBC_SHA"))
            engine.setEnabledProtocols(Array("SSLv3", "TLSv1"))
            engine
        }
    }
}

顺便说一句,Camel记录的错误更为有用.做一些愚蠢的事情,例如提供通往梯形失真的错误路径或输入错误的密码,会产生有意义的,人类可读的错误,而不是我之前看到的无声故障.

BTW, the errors logged by Camel were much more helpful. Doing something silly like providing a bad path to the keystone or an incorrect password gives meaningful, human-readable errors rather than the silent failure I was seeing previously.

这篇关于具有自签名证书的Spray https服务器的配置问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆