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