如何让 Play Framework WS 使用我的 SSLContext
How to make Play Framework WS use my SSLContext
我正在使用 Play 2.3.7 和 Scala 2.11.4,Java 7. 我想使用 Play WS 连接到 HTTPS 端点,这需要客户端提供其证书。为此,我创建了自己的 SSLContext:
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 一起使用?
您应该使用 https://www.playframework.com/documentation/2.3.x/KeyStores and https://www.playframework.com/documentation/2.3.x/ExampleSSLConfig 中定义的来自 application.conf 的客户端证书——如果您需要使用自定义配置,您应该直接使用解析器:
创建配置,然后是 Ning 构建器:
这将为您提供可以传入的 AHCConfig 对象。在 https://www.playframework.com/documentation/2.3.x/ScalaWS 的 "Using WSClient" 部分中有示例。
我正在使用 Play 2.3.7 和 Scala 2.11.4,Java 7. 我想使用 Play WS 连接到 HTTPS 端点,这需要客户端提供其证书。为此,我创建了自己的 SSLContext:
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 一起使用?
您应该使用 https://www.playframework.com/documentation/2.3.x/KeyStores and https://www.playframework.com/documentation/2.3.x/ExampleSSLConfig 中定义的来自 application.conf 的客户端证书——如果您需要使用自定义配置,您应该直接使用解析器:
创建配置,然后是 Ning 构建器:
这将为您提供可以传入的 AHCConfig 对象。在 https://www.playframework.com/documentation/2.3.x/ScalaWS 的 "Using WSClient" 部分中有示例。