2

H.e.l.l.o community, i hope someone can help me ... i am using apache tomcat 8.0.0-RC5 and JSR-356 web socket API ... I have 2 questions:

1) Is it possible to get the client ip on @OnOpen method ??

2) Is it possible to get the origin of the connection ???

I followed the websocket example which comes with the distribution of tomcat and i was not able to find the answers .... My java class is basically as follow

@ServerEndpoint(value = "/data.socket")
public class MyWebSocket {
    @OnOpen
    public void onOpen(Session session) {
        // Here is where i need the origin and remote client address
    }

    @OnClose
    public void onClose() {
        // disconnection handling
    }

    @OnMessage
    public void onMessage(String message) {
        // message handling
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        // Error handling
    }
}
user2926082
  • 21
  • 1
  • 3

2 Answers2

0

Repeating the answer I already gave you on the Tomcat users mailing list...

Client IP. No. Generally this type of information is available at the handshake which occurs before OnOpen but client IP is not one of the pieces of information exposed. You might be better blocking these earlier e.g. with iptables or similar.

Origin. ServerEndpointConfig.Configurator.checkOrigin(String) You'll need a custom Configurator. Keep in mind that a malicious client can forge the origin header.

Mark Thomas
  • 16,339
  • 1
  • 39
  • 60
  • jaja, yes it is true, hi Mark ... i wanted to be sure someone would answer my question :) ... by the way, why client ip is not exposed ... is it for security reasons ?? ... or, it is because it possible to change the ip while keeping the same connection ... – user2926082 Oct 29 '13 at 14:07
  • Really, why client ip is not exposed ? ... i use it to make a query to ipinfodb.com to get an approximate location ... – user2926082 Oct 30 '13 at 15:17
  • An oversight in the specification. None of the EG thought to add it and no one who reviewed and commented on the numerous drafts raised it as an issue. – Mark Thomas Oct 30 '13 at 19:48
0

I know this question is old, but just in case someone else finds it in a web search:

Yes there is an easy workaround. A Servlet can receive and forward a WebSocket upgrade request. The trick is to get the client IP address and expose it as a parameter.

Here's your servlet code:

@WebServlet("/myExternalEntryPoint")
public class WebSocketServlet extends HttpServlet {
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        var dispatcher = getServletContext().getRequestDispatcher("/myInternalEntryPoint");
        var requestWrapper = new MyRequestWrapper(request);
        dispatcher.forward(requestWrapper, response);
    }
}

And here's MyRequestWrapper:

class MyRequestWrapper extends HttpServletRequestWrapper {
    public RequestWrapper(HttpServletRequest request) {
        super(request);
    }

    public Map<String, String[]> getParameterMap() {
        return Collections.singletonMap("remoteAddr", new String[] {getRequest().getRemoteAddr()});
    }
}

Now in your WebSocket implementation, you'll be able to get remoteAddr via javax.websocket.Session.getRequestParameterMap().

Naturally, if your original request has parameters that you care about, you'll need to create a map that includes those as well. Also I recommend you append a separate, secret parameter and check for it in your WebSocket code to prevent anyone from hitting the internal entry point directly.

I figured out this was possible because of this thoughtful comment in the Tomcat source code (WsFilter.java):

// No endpoint registered for the requested path. Let the
// application handle it (it might redirect or forward for example)
Ian Lovejoy
  • 376
  • 4
  • 7