我使用Play 2.3.7与Scala 2.11.4,Java 7.我想使用Play WS连接到HTTPS端点,需要客户端提交其证书。要做到这一点我创造我自己的SSL连接:如何使播放框架WS使用我的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")
}
我也得到了同样的异常的时候我会萨金特的建议后去使用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") }
}
如何使其与播放WS工作?
我按照你的建议去了,但不幸的是它不起作用 - 请看最新的问题 – 2015-02-12 19:33:44
你需要打开ws.ssl.debug并查看连接终止的原因。请参阅https://www.playframework.com/documentation/2.3.x/DebuggingSSL – 2015-02-12 20:21:20
我看到的差异之一是SSL hello中的server_name扩展名存在于成功的案例中。你可以强迫Play WS把它放在那里吗? – 2015-02-12 21:14:53