Web services 如何让Play Framework WS使用我的SSLContext
我将Play2.3.7与Scala2.11.4、Java7一起使用。我想使用Play WS连接到HTTPS端点,该端点要求客户端提供其证书。为此,我创建了自己的SSLContext:Web services 如何让Play Framework WS使用我的SSLContext,web-services,ssl,Web Services,Ssl,我将Play2.3.7与Scala2.11.4、Java7一起使用。我想使用Play WS连接到HTTPS端点,该端点要求客户端提供其证书。为此,我创建了自己的SSLContext: val sslContext = { val keyStore = KeyStore.getInstance("pkcs12") keyStore.load(new FileInputStream(clientKey), clientKeyPass.to[Array]) val kmf
val sslContext = {
val keyStore = KeyStore.getInstance("pkcs12")
keyStore.load(new FileInputStream(clientKey), clientKeyPass.to[Array])
val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm)
kmf.init(keyStore, clientKeyPass.to[Array])
val trustStore = KeyStore.getInstance("jks")
trustStore.load(new FileInputStream(trustStoreFile), trustStorePass.to[Array])
val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
tmf.init(trustStore)
val ctx = SSLContext.getInstance("TLSv1.2")
ctx.init(kmf.getKeyManagers, tmf.getTrustManagers, new SecureRandom())
ctx
}
我知道SSLContext是有效的,因为我可以将它成功地用于URLConnection:
def urlConnection = Action {
val conn = new URL(url).openConnection()
conn.asInstanceOf[HttpsURLConnection].setSSLSocketFactory(sslContext.getSocketFactory)
conn.connect()
Ok(scala.io.Source.fromInputStream(conn.getInputStream).getLines().mkString("\n"))
}
但当我尝试下面两种方法中的一种时,我得到了java.nio.channels.ClosedChannelException
def ning = Action.async {
val builder = new AsyncHttpClientConfig.Builder()
builder.setSSLContext(sslContext)
val client = new NingWSClient(builder.build())
client.url(url).get() map { _ => Ok("ok") }
}
def asyncHttpClient = Action {
val builder = new AsyncHttpClientConfig.Builder()
builder.setSSLContext(sslContext)
val httpClient = new AsyncHttpClient(builder.build())
httpClient.prepareGet(url).execute().get(10, TimeUnit.SECONDS)
Ok("ok")
}
当我按照Will Sargent的建议使用NingAsyncHttpClientConfigBuilder和解析的配置注释时,我也会遇到同样的异常,即配置引用的值与手工编制的sslContext完全相同
def ningFromConfig = Action.async {
val config = play.api.Configuration(ConfigFactory.parseString(
s"""
|ws.ssl {
| keyManager = {
| stores = [
| { type: "PKCS12", path: "$clientKey", password: "$clientKeyPass" }
| ]
| }
| trustManager = {
| stores = [
| { type: "JKS", path: "$trustStoreFile", password: "$trustStorePass" },
| ]
| }
|}
|# Without this one I get InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
|ws.ssl.disabledKeyAlgorithms="RSA keySize < 1024"
""".stripMargin))
val parser = new DefaultWSConfigParser(config, play.api.Play.application.classloader)
val builder = new NingAsyncHttpClientConfigBuilder(parser.parse())
val client = new NingWSClient(builder.build())
client.url(url).get() map { _ => Ok("ok") }
}
如何使其与Play WS一起工作?您应该使用和中定义的application.conf中的客户端证书-如果需要使用自定义配置,您应该直接使用解析器: 要创建一个配置,请使用Ning生成器:
这将为您提供可以传入的AHCConfig对象。在。的“使用WSClient”一节中有一些示例,我遵循了您的建议,但不幸的是,它不起作用-请查看更新的问题,您需要打开ws.ssl.debug并查看连接终止的原因。我看到的一个区别是,在成功案例中,SSL hello中存在服务器名称扩展。你能强迫Play WS将其放在那里吗?你需要首先确定连接失败的原因。你建议从哪里开始诊断?我刚刚打开了调试跟踪,比较了正负两种情况下的输出。在否定的情况下,我注意到服务器名称扩展名的缺失。我接受了威尔的答案,因为这可能是对原始问题最好的答案。在我的情况下,它不起作用是另一回事,但它需要关于这个特殊SSL设置的一些模糊细节,现在不可能复制。当时我使用Spray HTTP客户端Akka HTTP now解决了这个问题。