在 WebSocketServlet (Jetty WebSockets) 中访问在 HttpServlet 中设置的会话属性

Posted

技术标签:

【中文标题】在 WebSocketServlet (Jetty WebSockets) 中访问在 HttpServlet 中设置的会话属性【英文标题】:Accessing session attributes set in a HttpServlet in a WebSocketServlet (Jetty WebSockets) 【发布时间】:2020-06-30 09:04:50 【问题描述】:

我正在尝试从WebSocketServlet 访问在HttpServlet 中设置的会话属性

我有两个ServletContextHandler 对象,都启用了SESSIONS

val httpHandler = object : ServletContextHandler(nullParent, contextPath, SESSIONS).apply 
    addServlet(ServletHolder(httpServlet), "/*")


val webSocketHandler = ServletContextHandler(nullParent, contextPath, SESSIONS).apply 
    addServlet(ServletHolder(wsServlet), "/*")

这些作为HandlerList(httpHandler, webSocketHandler) 附加到我的码头ServerHttpHandlerServletContextHandlerdoHandle 的第一行检查请求是否是WebSocket 升级请求,如果是则立即返回(在这种情况下,它会移交给ServletContextHandler 用于@987654332 @)。

我有一个简单的POST 端点,它设置了一个会话属性,但我无法在WebSocketServlet 中检索此会话属性:

class MyWsServlet : WebSocketServlet() 

    override fun configure(factory: WebSocketServletFactory) 
        factory.creator = WebSocketCreator  req, res ->
            // session exists here, but req.session.getAttribute("any-attr") is always null
        
    

    override fun service(req: HttpServletRequest, res: HttpServletResponse) 
        // session also exists here, but req.session.getAttribute("any-attr") is always null
    


欢迎任何意见或建议。

编辑:在调用req.session.setAttribute("test", "tast") 之后,我已经包含了一些来自 GET 请求和 WebSocket 请求的调试信息:

Path: /
Cookies:JSESSIONID=node01cxyhb0addjwikyb2lgtnlxlw0.node0
Session: Session@24b04e4id=node01cxyhb0addjwikyb2lgtnlxlw0,x=node01cxyhb0addjwikyb2lgtnlxlw0.node0,req=1,res=true
Session id: node01cxyhb0addjwikyb2lgtnlxlw0
Session isNew: false
Session attributes: test=tast
---------------------------
Path: /websocket
Cookies:JSESSIONID=node01cxyhb0addjwikyb2lgtnlxlw0.node0
Session: Session@5989f3d1id=node01cxyhb0addjwikyb2lgtnlxlw0,x=node01cxyhb0addjwikyb2lgtnlxlw0.node0,req=1,res=true
Session id: node01cxyhb0addjwikyb2lgtnlxlw0
Session isNew: false
Session attributes: 

【问题讨论】:

【参考方案1】:

首先,摆脱你的 2 ServletContextHandler,使用一个。无论如何,你不能在同一个 contextPath 上有两个处理程序。

此外,您可以通过两种主要方式实现 Jetty Server WebSockets,使用 WebSocketServlet 或使用 WebSocketUpgradeFilter。最大的不同是使用WebSocketUpgradeFilter,你可以有多个映射指向任意数量的WebSocket端点,使用Servlet url-pattern notation,或URI-template notation,甚至是regex notation。

如果这样做后问题仍然存在,那么听起来您的客户端要么没有发送 Jetty 需要的 Cookie 标头,要么发送了错误的标头(例如:Cookie 标头指向不同的/新的HttpSession 参考)。

捕获客户端和服务器之间的流量,注意客户端的Cookie 值,以及服务器响应中看到的任何Set-Cookie 值。

您也可以有一个过滤器,只转储每个请求的活动HttpSession 详细信息。确保它显示HttpSession.getId()HttpSession.isNew() 并转储所有属性(通过.getAttributeNames()getAttribute(String name) 调用的组合)。

【讨论】:

> 首先,摆脱你的2个ServletContextHandler,使用一个。无论如何,您不能在同一个 contextPath 上拥有两个处理程序 --- 我不能将它们添加到同一个 ServletContextHandler(“多个 servlet 映射到路径 /*:”)。如果我想拥有相同的根路径,我该如何解决这个问题?我将更新我的问题以包含 cookie 和会话 ID。 使用WebSocketUpgradeFilter,而不是从WebSocketServlet扩展。 谢谢,在重写 WebSocketUpgradeFilter 后,我设法获得了会话属性!

以上是关于在 WebSocketServlet (Jetty WebSockets) 中访问在 HttpServlet 中设置的会话属性的主要内容,如果未能解决你的问题,请参考以下文章

jetty 支持内嵌ssh项目吗,为啥在tomcat下面正常的war 放到jetty就跑不起来

Jetty实战之 嵌入式运行Jetty 配置Https

Jetty使用教程——开始使用Jetty

Jetty项目解压目录设置

使用 jetty-maven-plugin 运行 Jetty,并在 jetty 运行时完成构建

Jetty 在关机时抛出 NoClassDefFoundError: org/eclipse/jetty/util/FutureCallback