Playframework 2,Websockets和Session

时间:2012-10-14 05:24:25

标签: session websocket playframework-2.0 session-cookies

据我所知,在处理websockets时,我无法使用session。 playframework 2 websocket聊天示例将用户名添加到网址中,但是如果我有一个用户已经插入并且我不想通过网址传递他的用户名,那么还有另一种方法可以从内部获取用户登录凭据一个websocket请求?

这是我到目前为止所尝试的内容: 从我将连接到套接字的请求页面:

public static Result index(){
    session("username", "mike")
    return ok(indexpage.render());
}

这是Websocket部分:

public static Websocket<JsonNode> chat(){
    System.out.println(session("username"));    
    ....all the websocket stuff
}

我打印出的所有内容都是空的 我做错了什么?

3 个答案:

答案 0 :(得分:3)

您可以访问会话:

package controllers

import play.api._
import play.api.mvc._
import play.api.libs.iteratee._

object Application extends Controller {
  def index = Action {
    Ok(views.html.index()).withSession("connected" -> "user@gmail.com")
  }

  //I used for views.html.index the html markup from http://www.websocket.org/echo.html
  def wstest = WebSocket.using[String] { request =>

    val in = Iteratee.consume[String]()

    val username = request.session.get("connected").getOrElse("missing username")

    val out = Enumerator("Hello " + username) //puts  Hello user@gmail.com on the screen

    (in, out)
  }
}

好的,现在用于Java(控制器中的方法):

public static WebSocket<String> chat(){
    final Http.Session session = session();
    final String name = session("username");//better version

    return new WebSocket<String>() {
        public void onReady(WebSocket.In<String> in, WebSocket.Out<String> out) {
            in.onMessage(new F.Callback<String>() {
                public void invoke(String event) {
                    System.out.println(event);
                }
            });

            in.onClose(new F.Callback0() {
                public void invoke() {
                    System.out.println("Disconnected");
                }
            });

            out.write("Hello " + session.get("username"));
            out.write("Hello " + name);
        }
    };
}

您似乎无法直接访问websocket创建中的http上下文,但您可以将Cookie中的会话或更好的数据存储在常量中,并在创建WebSocket实例时使用它。

我上传了一个带有测试https://github.com/schleichardt/stackoverflow-answers/tree/so12879547的Java示例(它不在主分支上)。

PS: 在WebSocket创建中没有起作用:

Http.Context.current().session().get("username")

答案 1 :(得分:1)

websocket连接不是Http。第一个握手请求看起来有点像http,但确实包含其他字段。这就是为什么你不能在websocket请求中添加你的http cookie。

来自维基百科:

  

握手类似于HTTP,因此服务器可以处理HTTP   连接以及同一端口上的WebSocket连接。然而   涉及的具体领域,以及握手后的内容   不符合HTTP协议。

如果您不想在那里使用用户名,可以在URL中使用令牌/会话ID,或者如果在启动websocket连接之前无法实现login / pw检索,则可以实现自己的登录方法/通过websocket通信检索密码(例如服务器要求以特定格式登录/ pw,客户端js做出反应,收集并将其发送回服务器)。

答案 2 :(得分:1)

允许访问Session,因为它初始化为HTTP握手。 您可以通过将其粘贴到会话来定义您的用户名密钥,来自经过身份验证的操作的值:

Redirect(.....).withSession("login" -> user)

然后:

object WebsocketController extends Controller {

  def wsConnection = WebSocket.async[JsValue] { request =>

    val userOption: Option[String] = request.session.get("login")

    //do your credential check or login ....

    (in, out)
  }

}

这确实是由playframework

保护的