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;
}
}