tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Bob DeRemer <bob.dere...@thingworx.com>
Subject Possible serious bug in Tomcat 7's websocket UpgradeUtil when handling concurrent connections that use a custom ServerEndpointConfig.Configurator
Date Sun, 27 Oct 2013 12:03:09 GMT
It appears that there is a problem in Tomcat's static UpgradeUtil.doUpgrade logic when handling
concurrent connection/upgrade requests that rely on a custom ServerEndpointConfig.Configurator.modifyHandshake
to grab [per-upgrade-request] client header values and inject them into the wsSession that
is being created.

Specifically, the static doUpgrade does not appear to make a copy of the ServerEndpointConfig
before calling modifyHandshake.   As a result, any per-connection headers the Configurator
may grab and put in the ServerEndpointConfig.UserProperties map will be overwritten by the
last upgrade request that occurs before the upgrade logic creates the new wsSession in the
WsHttpUpgradeHandler.init call.

I am able to replicate this very easily by using the following server configurator code. 
By making concurrent websocket connect requests that place a unique "client-id" in the upgrade
request headers, then grabbing that "client-id" property using the code below, ALL websocket
sessions that get created will have the last "client-id" header value that came in concurrently.

public class Jsr356ServerConfigurator extends ServerEndpointConfig.Configurator
{
    @Override
    public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse
response)
    {
              // get the request headers - looking for security claims and endpoint ID
              // claims will be checked in the OnOpen call and the connection closed if AUTH
check fails
              Map<String, List<String>> headers = request.getHeaders();

              String id = headers.get("client-id").get(0);

              config.getUserProperties().put("client-id", id);
    }
}

@ServerEndpoint(...)
Public class MyServer
{
@OnOpen
public void onOpen(Session session)
{
              String id = (String) session.getUserProperties().get("client-id");
              _logger.warn("client ID: {}", id);
}
}


Based on chapter 3 of the JSR-356 API document, the actual websocket handshake process defined
in the websocket spec,  and the online description of the process in this stackoverflow link
(http://stackoverflow.com/questions/17936440/accessing-httpsession-from-httpservletrequest-in-a-web-socket-socketendpoint/17994303#17994303),
it appears that we should be able to pass per-client information in the upgrade headers and
we should be able to get them into the endpoint INSTANCE's Session user properties.

If this is a bug, please confirm and I will create a bugzilla entry, as it is very important
that that we be able to do what I've described above.

If this is not a bug, can someone please describe how to obtain per-client instance data during
the handshake/onOpen process?


Thanks,
Bob

http://www.thingworx.com<http://www.thingworx.com/>
Skype: bob.deremer.thingworx


Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message