2015-02-11 19 views
-1

我使用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工作?

回答

0
+0

我按照你的建议去了,但不幸的是它不起作用 - 请看最新的问题 – 2015-02-12 19:33:44

+0

你需要打开ws.ssl.debug并查看连接终止的原因。请参阅https://www.playframework.com/documentation/2.3.x/DebuggingSSL – 2015-02-12 20:21:20

+0

我看到的差异之一是SSL hello中的server_name扩展名存在于成功的案例中。你可以强迫Play WS把它放在那里吗? – 2015-02-12 21:14:53