从播放应用程序访问SSL安全网页

时间:2012-08-10 12:35:57

标签: web-services ssl playframework playframework-2.0

我正在从Play应用访问SSL安全页面。 当页面证书无法信任时(因为它已过期或自签名或 无论其他原因可能是什么)我想从我的电话中提取这些信息 做一些相应的行动。 当我在浏览器中访问这样的页面时,它警告我有问题 证书。 当我在游戏中写这样的东西时(此处的https页面有一个错误的证书):

package controllers

import play.api.mvc.{Action, Controller}
import play.api.libs.ws.WS
import java.util.concurrent.TimeUnit

object CallHttpsController extends Controller{


  def callHttps() = Action {

    val url = "https://xceed.no-ip.org/"

    val response: play.api.libs.ws.Response = WS.url(url).get.await(3, TimeUnit.SECONDS).get

    response.status match {
      case OK => Ok("Got response: " + response.body)
      case _ => Ok("Something went wrong: "+response.status+" "+response.body)
    }
  }
}

响应状态是正常的,我希望它会抛出异常,说明有问题 凭证书。

是否可以在游戏中调用此类页面并在证书无法信任时获得异常? 是否支持播放默认? 有没有人有类似的问题/需要?

提前致谢。

更新#1: 感谢Ning的小费。 我已经在构建脚本中添加了依赖项:

  lazy val appDependencies = Seq(
    "com.ning" % "async-http-client" % "1.7.5"
  )

图书馆本身确实非常有用。但是,为了按预期使用SSL,显然它需要初始化SSL Context。我尝试了以下代码:

def callHttps() = Action {

    try{

      val url = "https://xceed.no-ip.org/"

      val response: play.api.libs.ws.Response = WS.url(url).get.await(3, TimeUnit.SECONDS).get // => No problem here

      Console.println(WS.client.getConfig.getSSLContext) // => null

      val sslContext = SSLContext.getDefault;
      val playConfig = play.api.Play.maybeApplication.map(_.configuration)
      val asyncHttpConfig = new AsyncHttpClientConfig.Builder()
    .setConnectionTimeoutInMs(playConfig.flatMap(_.getMilliseconds("ws.timeout")).getOrElse(120000L).toInt)
    .setRequestTimeoutInMs(playConfig.flatMap(_.getMilliseconds("ws.timeout")).getOrElse(120000L).toInt)
    .setFollowRedirects(playConfig.flatMap(_.getBoolean("ws.followRedirects")).getOrElse(true))
    .setUseProxyProperties(playConfig.flatMap(_.getBoolean("ws.useProxyProperties")).getOrElse(true))
    .setSSLContext( sslContext )

      playConfig.flatMap(_.getString("ws.useragent")).map { useragent =>
        asyncHttpConfig.setUserAgent(useragent)
      }
      val innerClient = new AsyncHttpClient(asyncHttpConfig.build())

      val resp = innerClient.prepareGet(url).execute().get() // => exception
      Console.println("All OK")

      Ok("Got response: " + resp.getResponseBody)

    }
    catch {
      case e: Exception =>
        var cause = e.getCause
        while (cause != null) {
          Console.println("Caused by: \n" + e.getLocalizedMessage + "\n" + e.getStackTraceString)
          cause = cause.getCause
        }

        Ok("Got Exception: " + e.getLocalizedMessage + "\n" + e.getStackTraceString)
    }
  }

从WS源代码中提取客户端初始化,并将默认SSL上下文传递给客户端。然后呼叫按预期失败。 将尝试提高票价... 干杯!

更新#2: 该票已经解决,将成为游戏2.0.4的一部分 https://play.lighthouseapp.com/projects/82401/tickets/655-ws-call-wont-fail-upon-https-call-to-a-page-with-wrong-certificate

更新#3: 现在默认设置默认的ssl上下文。要在应用程序配置文件集中关闭它,请设置ws.acceptAnyCertificate = true

有关更多信息,请参阅WS.scala代码: https://github.com/playframework/Play20/blob/master/framework/src/play/src/main/scala/play/api/libs/ws/WS.scala

1 个答案:

答案 0 :(得分:1)

在其play.api.libs.ws.WS课程中播放!框架使用Ning Async HTTP Client Library(版本1.7.0),后者又使用Netty network application framework(版本3.5)。 Netty负责SSL验证,但其结果由Async HTTP Client库处理。

似乎只在a recent commit of the Async HTTP Client library中正确修复了SSL验证,该验证仅包含在1.7.5版本中。您可以尝试将较新版本强制进入您的项目(即覆盖Play引用的1.7.0版本!),并可能会打开一个问题,以便下一个Play中可以包含较新的库版本!释放。