2012-08-10 110 views
2

我正在從遊戲應用程序訪問SSL受保護的頁面。 當頁面的證書不可信(因爲它已經過期或者是自簽名的,或者無論其他原因如何),我想從我的電話中提取這些信息,並且 做一些相應的操作。 當我在瀏覽器中訪問這樣一個頁面時,它會警告我 證書有問題。 當我寫的戲是這樣的(這裏的HTTPS頁面有一個壞的證書):從遊戲應用程序訪問SSL安全的網頁

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) 
    } 
    } 
} 

響應狀態是正常的,我希望它拋出一個異常,有什麼不對 與證書。

當證書不可信時,是否有可能調用這樣的頁面並獲得異常? 它在默認情況下支持嗎? 有沒有人有類似的問題/需要?

在此先感謝。

UPDATE#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: 票已經得到解決,將是發揮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 =真

見WS.scala代碼以獲取更多信息的應用程序配置文件: https://github.com/playframework/Play20/blob/master/framework/src/play/src/main/scala/play/api/libs/ws/WS.scala

回答

1

在其play.api.libs.ws.WS類遊戲!框架使用Ning Async HTTP Client Library(版本1.7.0),後者又使用Netty network application framework(版本3.5)。 Netty負責SSL驗證,但其結果由異步HTTP客戶端庫處理。

看來SSL驗證只適用於a recent commit of the Async HTTP Client library,該驗證僅包含在1.7.5版本中。您可以嘗試將新版本強制插入到您的項目中(即覆蓋由Play!引用的1.7.0版本),並且可能會打開一個問題,以便可以將新版本的庫版本包含在下一個Play!發佈。

+0

嗨,感謝您的回答,請參閱我的問題更新:) – 2012-08-13 12:56:34

+1

嗨,玩2.0.4現在將能夠進行安全通話: https://play.lighthouseapp。COM /項目/ 82401 /票/ 655-WS-呼叫不會失效,在-HTTPS的調用到一個頁面與 - 錯誤的證書 – 2012-10-10 11:52:19