You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Robert Winch <rw...@gmail.com> on 2014/06/25 18:48:12 UTC

WsSessionListener closes WebSocket Session on unprotected endpoint

= Description

I believe I may be experiencing a bug in Tomcat or simply misinterpreting
JSR 356. Any thoughts on how to resolve the issue or if I a bug should be
created would be welcome. To reproduce:

1) Authenticate to the application over HTTP. In my instance I am using
Spring Security which overrides the HttpServletRequest using an
HttpServletRequestWrapper

2) Open a WebSocket connection over an "unprotected endpoint"

3) Wait for the HttpSession to timeout while using the WebSocket connection.

4) When the HttpSession times out, the WebSocket connection is closed by
WsSessionListener

JSR 356 states

"If the websocket endpoint is not a protected resource, ... the user
identity ... *may* become invalid...without the websocket implementation
needing to close the connection". The full excerpt can be found below:

> In the case where a websocket endpoint is a protected resource in the web
> application (see Chapter 8), that is to say, requires an authorized user
to
> access it, then the websocket implementation must ensure that the
websocket
> endpoint does not remain connected to its peer after the underlying
> implementation has decided the authenticated identity is no longer valid.
> [WSC-7.2-3] This may happen, for example, if the user logs out of the
containing
> web application, or if the authentication times out or is invalidated for
some
> other reason.
>
> On the other hand, if the websocket endpoint is not a protected resource
in the
> web application, then the user identity under which an opening handshake
> established the connection may become invalid or change during the
operation of
> the websocket without the websocket implementation needing to close the
> connection.

Should the WebSocket connection be closed when the session expires in this
instance? Perhaps this is just that I am misunderstanding the JSR which
states *may* instead of *must*. I'm not sure that is the case since a must
in this phrasing does not make much sense. For what it is worth, Jetty does
not close the connection in this instance.

 Another point of interest is that we get a NullPointerException in the
WsServerContainer when unregistering the session. Is this a possible bug
since it is logged at SEVERE?

= Complete Example

You can find a complete example on github [1]. The steps to reproduce are:

1) Clone the repository and use the wssessionlistener branch or download
from [2]

2) Ensure you have installed Maven and run "mvn tomcat7:run"

3) Visit http://localhost:8080/spring-websocket-portfolio/traditional/

4) Authenticate with the username "fabrice" and the password "fab123"

5) Wait 1 minute (the session is set to expire in a minute)

6) The WebSocket session will be closed We also see the following
stacktraces in the terminal. For a formatted version of the stack see the
linked gist [3].

Jun 25, 2014 11:34:19 AM org.apache.catalina.session.StandardSession expire
SEVERE: Session event listener threw exception
java.lang.NullPointerException
at
org.apache.tomcat.websocket.server.WsServerContainer.unregisterAuthenticatedSession(WsServerContainer.java:367)
at
org.apache.tomcat.websocket.server.WsServerContainer.unregisterSession(WsServerContainer.java:344)
at
org.apache.tomcat.websocket.WsSession.sendCloseMessage(WsSession.java:494)
at org.apache.tomcat.websocket.WsSession.doClose(WsSession.java:417)
at org.apache.tomcat.websocket.WsSession.close(WsSession.java:394)
at
org.apache.tomcat.websocket.server.WsServerContainer.closeAuthenticatedSession(WsServerContainer.java:377)
at
org.apache.tomcat.websocket.server.WsSessionListener.sessionDestroyed(WsSessionListener.java:40)
at
org.apache.catalina.session.StandardSession.expire(StandardSession.java:808)
at
org.apache.catalina.session.StandardSession.isValid(StandardSession.java:658)
at
org.apache.catalina.session.ManagerBase.processExpires(ManagerBase.java:534)
at
org.apache.catalina.session.ManagerBase.backgroundProcess(ManagerBase.java:519)
at
org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1352)
at
org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1530)
at
org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1540)
at
org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1540)
at
org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1519)
at java.lang.Thread.run(Thread.java:744)

11:34:20 [clientOutboundChannel-9] WebSocketServerSockJsSession -
Terminating connection after failure to send message to client.
java.lang.IllegalArgumentException: Cannot send message after connection
closed.
at org.springframework.util.Assert.isTrue(Assert.java:65)
at
org.springframework.web.socket.adapter.AbstractWebSocketSession.sendMessage(AbstractWebSocketSession.java:97)
at
org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSession.writeFrameInternal(WebSocketServerSockJsSession.java:196)
at
org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.writeFrame(AbstractSockJsSession.java:336)
at
org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSession.sendMessageInternal(WebSocketServerSockJsSession.java:186)
at
org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.sendMessage(AbstractSockJsSession.java:251)
at
org.springframework.web.socket.handler.ConcurrentWebSocketSessionDecorator.tryFlushMessageBuffer(ConcurrentWebSocketSessionDecorator.java:126)
at
org.springframework.web.socket.handler.ConcurrentWebSocketSessionDecorator.sendMessage(ConcurrentWebSocketSessionDecorator.java:99)
at
org.springframework.web.socket.messaging.StompSubProtocolHandler.handleMessageToClient(StompSubProtocolHandler.java:327)
at
org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.handleMessage(SubProtocolWebSocketHandler.java:305)
at
org.springframework.messaging.support.ExecutorSubscribableChannel$1.run(ExecutorSubscribableChannel.java:70)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)


= Environment Information

Tomcat 8.0.8 and 7.0.47

OSX Mavericks

java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)

[1]
https://github.com/rwinch/spring-websocket-portfolio/tree/wssessionlistener

[2]
https://github.com/rwinch/spring-websocket-portfolio/archive/wssessionlistener.zip

[3] https://gist.github.com/rwinch/04c59fcacff4a4256030

Cheers,
Rob Winch