2

Play アプリから SSL で保護されたページにアクセスしています。ページの証明書が信頼できない場合 (有効期限が切れているか、自己署名されているか、その他の理由が考えられるため)、呼び出しからこの情報を抽出し、それに応じて何らかのアクションを実行したいと考えています。ブラウザでそのようなページにアクセスすると、証明書に問題があるという警告が表示されます。Play で次のようなものを書くと (ここの 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)
    }
  }
}

応答ステータスは OK で、証明書に問題があるという例外がスローされると予想されます。

そのようなページを呼び出して、証明書が信頼できない場合に例外を取得することは可能ですか? デフォルトでサポートされていますか? 誰かが同様の問題/ニーズを抱えていましたか?

前もって感謝します。

更新 #1: Ning とのヒントに感謝します。ビルド スクリプトに依存関係を追加しました。

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

ライブラリ自体は確かに非常に役立ちます。ただし、期待どおりに SSL を使用するには、SSL コンテキストを初期化する必要があるようです。次のコードを試しました:

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: チケットは現在解決されており、play 2.0.4 の一部になり ます https://play.lighthouseapp.com/projects/82401/tickets/655-ws-call-wont-fail-upon-https-間違った証明書を持つページへの呼び出し

更新 #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

4

1 に答える 1

1

そのplay.api.libs.ws.WSクラスでは、Play!フレームワークはNingAsyncHTTPクライアントライブラリ(バージョン1.7.0)を使用し、 Ning Async HTTPクライアントライブラリはNettyネットワークアプリケーションフレームワーク(バージョン3.5)を使用します。NettyはSSL検証を担当しますが、その結果は非同期HTTPクライアントライブラリによって処理されます。

SSL検証は、1.7.5リリースにのみ含まれている非同期HTTPクライアントライブラリの最近のコミットでのみ適切に修正されているようです。新しいバージョンをプロジェクトに強制して(つまり、Playが参照する1.7.0バージョンをオーバーライドして)、問題を開いて、新しいライブラリバージョンを次のPlay!に含めることができます。リリース。

于 2012-08-10T22:31:48.557 に答える