websockets messagemapping example spring spring-security websocket publish-subscribe spring-websocket

messagemapping - spring-websocket maven



Cómo rechazar la suscripción de temas según los derechos de usuario con Spring-websocket (2)

Estoy implementando una versión de la aplicación de valores en la que el servidor puede rechazar la suscripción de temas para ciertos temas según los derechos de los usuarios. ¿Hay alguna manera en Spring-websocket para hacer esto?

Por ejemplo:

En el proyecto de ejemplo de acciones tenemos tema de precio para 3 instrumentos: Apple, Microsoft, Google y tenemos dos usuarios: User1, User2

Usuario1 debe tener acceso a Apple y Microsoft Usuario2 debe tener acceso solo a Google

Si el Usuario1 se suscribe a Google, debería recibir una respuesta rechazada, y el mensaje no debería transmitirse a él después.


A partir de Spring 5.x, el método correcto para anular la conexión del interceptor, si está extendiendo AbstractSecurityWebSocketMessageBrokerConfigurer , es customizeClientInboundChannel :

@Override public void customizeClientInboundChannel(ChannelRegistration registration) { registration.interceptors(new TopicSubscriptionInterceptor()); }


Gracias a la respuesta de Rossen Stoyanchev en github, pude resolver esto agregando un interceptor al canal entrante. Los cambios necesarios en la aplicación de demostración spring-websocket-portfolio son los siguientes:

Cambiar la configuración de websocket:

public void configureClientInboundChannel(ChannelRegistration registration) { registration.setInterceptors(new TopicSubscriptionInterceptor()); }

Y el interceptor era algo así:

public class TopicSubscriptionInterceptor extends ChannelInterceptorAdapter { private static Logger logger = org.slf4j.LoggerFactory.getLogger(TopicSubscriptionInterceptor.class); @Override public Message<?> preSend(Message<?> message, MessageChannel channel) { StompHeaderAccessor headerAccessor= StompHeaderAccessor.wrap(message); if (StompCommand.SUBSCRIBE.equals(headerAccessor.getCommand())) { Principal userPrincipal = headerAccessor.getUser(); if(!validateSubscription(userPrincipal, headerAccessor.getDestination())) { throw new IllegalArgumentException("No permission for this topic"); } } return message; } private boolean validateSubscription(Principal principal, String topicDestination) { if (principal == null) { // unauthenticated user return false; } logger.debug("Validate subscription for {} to topic {}",principal.getName(),topicDestination); //Additional validation logic coming here return true; }

}