如何在 Play!Framework WebSockets ("wss://") 中使用 TLS
Posted
技术标签:
【中文标题】如何在 Play!Framework WebSockets ("wss://") 中使用 TLS【英文标题】:How to use TLS in Play!Framework WebSockets ("wss://") 【发布时间】:2013-10-25 13:03:06 【问题描述】:我无法在使用 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
我怎样才能做到这一点?谢谢。
【问题讨论】:
【参考方案1】:我真的很想为你解决这个问题!但我不喜欢这个答案。似乎还没有针对 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 如此轻巧有趣。会毫不犹豫地选择这个选项。
【讨论】:
我会推荐 EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128 :+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128 -SHA 来自bettercrypto.org【参考方案2】:您是否尝试在 Play 服务器上启用 https 支持?看起来您正在尝试使用 wss 连接到 http 端口,但始终无法正常工作,您需要启用 https,然后将 URL 不仅更改为 wss,还更改为使用 https 端口。
在开启 ssl 的情况下启动 Play 服务器:
activator run -Dhttps.port=9443
然后连接到wss://localhost:9443/ws2
。
【讨论】:
【参考方案3】:wss
适用于 Play 2.6。
您可以通过路由获取 url,而不是硬编码 websocket url:
@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>
【讨论】:
【参考方案4】:另一种选择是使用 SockJS 作为 Websocket 层,Play2 的 SockJS 实现可以在 https://github.com/fdimuccio/play2-sockjs
启用 HTTPS 后,SockJS 通过 HTTPS 通道创建一个 wss 端点。 Play2-sockjs 也支持 Actor 模式,就像原生 Play websockets 一样。
如果你不想在客户端使用 SockJS 而是强制浏览器 websocket 实现,你可以使用显式 websocket 端点 wss:////websocket
【讨论】:
以上是关于如何在 Play!Framework WebSockets ("wss://") 中使用 TLS的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Play Framework 1.2 中实现 HTTP Basic Auth?
如何在 Play Framework JSON Rest 上使用 java.time.LocalDate?
如何在 Play!Framework WebSockets ("wss://") 中使用 TLS