How to use TLS in Play!Framework WebSockets (“wss://”)

北战南征 提交于 2019-11-27 19:53:11

I really wanted to figure this out for you! But I didn't like the answer. It appears there's no Play support yet for SSL for websockets. Saw mention of it here and no sign of progress since: http://grokbase.com/t/gg/play-framework/12cd53wst9/2-1-https-and-wss-secure-websocket-clarifications-and-documentation

However, there's hope! You can use nginx as a secure websocket (wss) endpoint, to forward to a internal play app with a insecure websocket endpoint:

The page http://siriux.net/2013/06/nginx-and-websockets/ provided this explanation and sample proxy config for nginx:

Goal: WSS SSL Endpoint: forwards wss|https://ws.example.com to ws|http://ws1.example.com:10080

"The proxy is also an SSL endpoint for WSS and HTTPS connections. So the clients can use wss:// connections (e.g. from pages served via HTTPS) which work better with broken proxy servers, etc."

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 is so lightweight and fun. Would not hesitate to go with this option.

Did you try enabling https support on the Play server? It looks like you're trying to connect to the http port using wss, that can never work, you need to enable https, and then change the URL not just to wss, but also to use the https port.

To start a Play server with ssl turned on:

activator run -Dhttps.port=9443

Then connect to wss://localhost:9443/ws2.

wss works fine with Play 2.6.

Instead of hardcode the websocket url, you can get the url via routes:

@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>

Another option is to use SockJS as the Websocket layer, SockJS implementation for Play2 can be found at https://github.com/fdimuccio/play2-sockjs

When HTTPS is enabled an wss endpoind is created by SockJS over the HTTPS channel. Play2-sockjs also supports the Actor pattern as with native Play websockets.

If you don't want to use SockJS in the clientside but rather force browser websocket implementation, you can use explicit websocket endpoint wss:////websocket

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!