I have added custom token based authentication for my spring-web app and extending the same for spring websocket as shown below
public class WebSocketConfig
In your Websocket controller you should do something like this :
@Controller
public class GreetingController {
@Autowired
private SimpMessagingTemplate messagingTemplate;
@MessageMapping("/hello")
public void greeting(Principal principal, HelloMessage message) throws Exception {
Greeting greeting = new Greeting();
greeting.setContent("Hello!");
messagingTemplate.convertAndSendToUser(message.getToUser(), "/queue/reply", greeting);
}
}
On the client side, your user should subscribe to topic /user/queue/reply.
You must also add some destination prefixes :
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic", "/queue" ,"/user");
config.setApplicationDestinationPrefixes("/app");
config.setUserDestinationPrefix("/user");
}
/*...*/
}
When your server receive a message on the /app/hello queue, it should send a message to the user in your dto. User must be equal to the user's principal.
I think the only problem in your code is that your "/user" is not in your destination prefixes. Your greetings messages are blocked because you sent them in a queue that begin with /user and this prefixe is not registered.
You can check the sources at git repo : https://github.com/simvetanylen/test-spring-websocket
Hope it works!
In my previous project I sent messages to one specific user; in detail I wrote the following:
CLIENT SIDE:
function stompConnect(notificationTmpl)
{
var socket = new SockJS('/comm-svr');
stompClient = Stomp.over(socket);
var theUserId
stompClient.connect({userId:theUserId}, function (frame) {
debug('Connected: ' + frame);
stompClient.subscribe('/topic/connect/'+theUserId, function (data) {
//Handle data
}
});
}
SERVER SIDE
Spring websocket listener:
@Component
public class WebSocketSessionListener
{
private static final Logger logger = LoggerFactory.getLogger(WebSocketSessionListener.class.getName());
private List<String> connectedClientId = new ArrayList<String>();
@EventListener
public void connectionEstablished(SessionConnectedEvent sce)
{
MessageHeaders msgHeaders = sce.getMessage().getHeaders();
Principal princ = (Principal) msgHeaders.get("simpUser");
StompHeaderAccessor sha = StompHeaderAccessor.wrap(sce.getMessage());
List<String> nativeHeaders = sha.getNativeHeader("userId");
if( nativeHeaders != null )
{
String userId = nativeHeaders.get(0);
connectedClientId.add(userId);
if( logger.isDebugEnabled() )
{
logger.debug("Connessione websocket stabilita. ID Utente "+userId);
}
}
else
{
String userId = princ.getName();
connectedClientId.add(userId);
if( logger.isDebugEnabled() )
{
logger.debug("Connessione websocket stabilita. ID Utente "+userId);
}
}
}
@EventListener
public void webSockectDisconnect(SessionDisconnectEvent sde)
{
MessageHeaders msgHeaders = sde.getMessage().getHeaders();
Principal princ = (Principal) msgHeaders.get("simpUser");
StompHeaderAccessor sha = StompHeaderAccessor.wrap(sde.getMessage());
List<String> nativeHeaders = sha.getNativeHeader("userId");
if( nativeHeaders != null )
{
String userId = nativeHeaders.get(0);
connectedClientId.remove(userId);
if( logger.isDebugEnabled() )
{
logger.debug("Connessione websocket stabilita. ID Utente "+userId);
}
}
else
{
String userId = princ.getName();
connectedClientId.remove(userId);
if( logger.isDebugEnabled() )
{
logger.debug("Connessione websocket stabilita. ID Utente "+userId);
}
}
}
public List<String> getConnectedClientId()
{
return connectedClientId;
}
public void setConnectedClientId(List<String> connectedClientId)
{
this.connectedClientId = connectedClientId;
}
}
Spring websocket message sender:
@Autowired
private SimpMessagingTemplate msgTmp;
private void propagateDvcMsg( WebDeviceStatusInfo device )
{
String msg = "";
String userId =((Principal)SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getName()
msgTmp.convertAndSend("/topic/connect"+userId, msg);
}
I hope it's useful