Reputation: 143
I am working on this for 3 weeks now without a real solution and I really hope you can help me out.
A bit project background:
Webapp with a JavaScript/PHP based Client sends via SocksJS and Stomp a message to a "gate"
The gate is written in Java/Spring and uses @SendTo and @MessageMapping to send and recieve messages
The messages from the gate are sent to RabbitMQ and back to the client via "messageBrokerRegistry.enableStompBrokerRelay"
So far it works, messages being sent are coming back.
Now the advanced SECURITY part:
WebSockets themselves dont support security as far as I understood. You have to secure your webapp just like a "common" webapp with BASIC auth or some like that. So I added a servlet filter with a class extending GenericFilterBean. If the user sent the correct cookie the page loads, else he gets a 403 error.
Now comes the PROBLEM:
Due to the fact that @SendTo sends messages to all subscribers and @SendToUser seems to send it just to one session I tend to use @SendToUser. BUT there seems no way to chose a rabbitMQ queue to be created. I want some like "/myqueue-user-123". This is not possible with @SendToUser, because the generated queue is random and based on the SessionID, which I could not override.
So what I tried (and i tried LOADS of stuff besides interceptors, events and so on), is using @SendTo without a value so that the client can decide the queue it has to send to.
What I need now is to evaluate that the user from the cookie correlates with "/myqueue/user-123". And if NOT, DO NOT SEND the message to him. Stop him from subscribing. Disconnect him, whatever.
But it seems to me that you can in no way - stop messages from being sent, just "intercept" to log them not alter - disconnect a websocket because it automatically tries reconnecting - throw exceptions because the subscribe suceeds anyways (events are just events, not something to interfere).
I would be really thankful for any advice or tip. Because I am totally stuck here...
Upvotes: 1
Views: 575
Reputation: 7872
I understand your pain, i spend two days trying to understand the spring security mess concerning WebSocket.
Websocket dont officially
support a way to authenticate, however, spring-security does (more or less).
I would advice you to authenticate at WebSocket level, not at HTTP, most of JavaScripts library for WebSocket (and stomp) don't sends headers along with the HTTP handshake.
You'll find a detailed guide on how to authenticate at the WebSocket level here. In the above example, i used Websocket Headers values to authenticate my clients, you can put your cookie value in these headers, or replace the cookie by localstorage.
Using this method you'll have access to the Principal
in your controllers, this should solve the SendToUser issue.
Upvotes: 2