Playframework 2,Websockets 和 Session

Posted

技术标签:

【中文标题】Playframework 2,Websockets 和 Session【英文标题】:Playframework 2, Websockets and Session 【发布时间】:2012-10-14 05:24:25 【问题描述】:

我了解在处理 websockets 时,我不能使用 session。 playframework 2 websocket 聊天示例将用户名添加到 url,但是如果我有一个已经登录的用户并且我不想通过 url 传递他的用户名,还有另一种方法可以从内部获取用户登录凭据一个 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

我打印出来的都是空的 我做错了什么?

【问题讨论】:

【参考方案1】:

您可以访问会话:

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/***-answers/tree/so12879547 的 Java 示例(它不在 master 分支上)。

PS: 这在 WebSocket 创建中不起作用:

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

【讨论】:

感谢您的回复,不幸的是我正在使用java,忘记提及了。这是我目前尝试过的,无法添加代码来评论,我会回复 我已经尝试了你的建议,添加了“最终的 Http.Session session = session()”,但是当我尝试从会话中提取用户名时,我仍然得到 null。非常感谢您在这方面的帮助。 如果你尝试'final String name = session("username");'在构造 WebSocket 之前?您确定您确实将名称存储到会话中吗?谷歌浏览器可以向您显示您的 Cookie。您可以在 github 上发布您的项目或最小示例吗? Did 'final String name = session("username"); return new WebSocket() ... Logger.info(name) ...' 为你工作 Mike? 我添加了一个带有测试的 Java 示例,请试试这个。【参考方案2】:

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

来自***:

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

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

【讨论】:

【参考方案3】:

在初始化为HTTP握手时允许访问Session。 您可以通过将其粘贴到会话中来定义您的用户名键、已验证操作的值:

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 保护的

【讨论】:

以上是关于Playframework 2,Websockets 和 Session的主要内容,如果未能解决你的问题,请参考以下文章

Playframework 2,Websockets 和 Session

在 PlayFramework 中测试 WebSocket

Play Framework 2.3 和 javascript websocket 客户端库

Play Framework - 是不是可以在 Play 中结合使用 Promise 和 WebSocket?

播放框架1.2.5 Websocket

Play Framework,Scala - 仅当有新数据可用时才向客户端发送 websocket 消息