如何在Play!Framework WebSockets中使用TLS(“wss://”)

时间:2013-10-25 13:03:06

标签: ssl playframework websocket playframework-2.2

我无法在使用Play!Framework 2.2创建的简单WebSocket应用中使用wss://。它回复了消息。端点就像这样

def indexWS2 = WebSocket.using[String] {
  request => {
    println("got connection to indexWS2")

    var channel: Option[Concurrent.Channel[String]] = None
    val outEnumerator: Enumerator[String] = Concurrent.unicast(c => channel = Some(c))

    // Log events to the console
    val myIteratee: Iteratee[String, Unit] = Iteratee.foreach[String] {gotString => {
      println("received: " + gotString)

      // send string back
      channel.foreach(_.push("echoing back \"" + gotString + "\""))
    }}

    (myIteratee, outEnumerator)
  }
}

,路线描述为

GET     /ws2                        controllers.Application.indexWS2

我从像这样的

这样的JS客户端创建连接
myWebSocket = new WebSocket("ws://localhost:9000/ws2");

一切正常。但是,如果我将ws://更改为wss://以使用TLS,则会失败并且我会收到以下Netty异常:

[error] p.nettyException - Exception caught in Netty
java.lang.IllegalArgumentException: empty text

我该如何使这项工作?感谢。

4 个答案:

答案 0 :(得分:11)

我真的想为你解决这个问题!但我不喜欢这个答案。对于websockets,SSL似乎还没有Play支持。在这里提到它并且没有任何进展的迹象,因为: http://grokbase.com/t/gg/play-framework/12cd53wst9/2-1-https-and-wss-secure-websocket-clarifications-and-documentation

然而,有希望!您可以使用nginx作为安全的websocket(wss)端点,使用不安全的websocket端点转发到内部播放应用程序:

页面http://siriux.net/2013/06/nginx-and-websockets/为nginx提供了此解释和示例代理配置:

目标:WSS SSL端点:forwards wss|https://ws.example.com to ws|http://ws1.example.com:10080

“代理也是WSS和HTTPS连接的SSL端点。因此客户端可以使用wss://连接(例如,通过HTTPS提供的页面),这些连接可以更好地与损坏的代理服务器等一起使用。”

server {
    listen       443;
    server_name  ws.example.com;

    ssl on;
    ssl_certificate ws.example.com.bundle.crt;
    ssl_certificate_key ws.example.com.key;
    ssl_session_timeout 5m;
    ssl_protocols  SSLv2 SSLv3 TLSv1;
    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers   on;

    location / {

        # like above

    }
}

Nginx非常轻巧有趣。会毫不犹豫地选择这个选项。

答案 1 :(得分:7)

您是否尝试在Play服务器上启用https支持?看起来您正在尝试使用wss连接到http端口,这种情况永远不会起作用,您需要启用https,然后将URL更改为wss,还要使用https端口。

要在启用ssl的情况下启动Play服务器:

activator run -Dhttps.port=9443

然后连接到wss://localhost:9443/ws2

答案 2 :(得分:1)

wss适用于Play 2.6。

您可以通过路线获取网址,而不是对websocket网址进行硬编码:

@import play.api.mvc.RequestHeader
@import controllers.routes
@()(implicit request: RequestHeader)
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>...</title>
        <script>
                var wsUri = "@routes.MyController.indexWS2().webSocketURL(secure = true)";
                var webSocket = new WebSocket(wsUri);
        //...
        </script>
    </head>
    <body>
    ...
    </body>
</html>

答案 3 :(得分:0)

另一个选择是使用SockJS作为Websocket层,可以在以下位置找到Play2的SockJS实现 https://github.com/fdimuccio/play2-sockjs

启用HTTPS后,SockJS会通过HTTPS通道创建wss endpoind。 Play2-sockjs也支持Actor模式,就像本地Play websockets一样。

如果您不想在客户端使用SockJS,而是强制使用浏览器websocket实现,则可以使用显式的websocket端点wss://// websocket