Sto utilizzando Spring STOMP su un'implementazione WebSocket con un broker ActiveMQ completo. Quando gli utenti SUBSCRIBE
a un argomento, c'è qualche logica di permessi che devono passare prima di essere iscritti con successo. Sto usando un ChannelInterceptor di applicare la logica delle autorizzazioni, come configurato di seguito:Come inviare un messaggio ERROR ai client STOMP con Spring WebSocket?
WebSocketConfig.java:
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/stomp")
.setAllowedOrigins("*")
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableStompBrokerRelay("/topic", "/queue")
.setRelayHost("relayhost.mydomain.com")
.setRelayPort(61613);
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(new MySubscriptionInterceptor());
}
}
WebSocketSecurityConfig.java:
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.simpSubscribeDestMatchers("/stomp/**").authenticated()
.simpSubscribeDestMatchers("/user/queue/errors").authenticated()
.anyMessage().denyAll();
}
}
MySubscriptionInterceptor.java:
public class MySubscriptionInterceptor extends ChannelInterceptorAdapter {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor headerAccessor= StompHeaderAccessor.wrap(message);
Principal principal = headerAccessor.getUser();
if (StompCommand.SUBSCRIBE.equals(headerAccessor.getCommand())) {
checkPermissions(principal);
}
return message;
}
private void checkPermissions(Principal principal) {
// apply permissions logic
// throw Exception permissions not sufficient
}
}
Quando i client che non dispongono di autorizzazioni adeguate tentano di iscriversi a un argomento limitato, non ricevono mai alcun messaggio dall'argomento, MA non ricevono alcuna notifica dell'eccezione generata che ha rifiutato l'abbonamento. Invece, il client viene restituito un abbonamento morto che il broker ActiveMQ non sa nulla. (Normale, le interazioni dei clienti in modo adeguato-gestite le autorizzazioni con l'endpoint STOMP e argomenti funzionare come previsto.)
ho cercato la sottoscrizione di users/{subscribingUsername}/queue/errors
e semplicemente users/queue/errors
con il mio client di test di Java dopo che è stato collegato con successo, ma non ho finora stato impossibile ottenere una sorta di messaggio di errore sull'eccezione di sottoscrizione dal server consegnato al client. Questo è ovviamente meno ideale dato che i client non vengono mai informati che gli è stato negato l'accesso.
Grazie per questo @Artem, ho dato un tentativo. Sfortunatamente, quando un'eccezione viene lanciata nel metodo '@ SubscribeMapping' e gestita dal metodo' @ MessageExceptionHandler', un messaggio viene inviato alla coda degli errori del client, MA la loro sottoscrizione viene comunque inoltrata al broker e il client continua a ricevere i messaggi successivi dall'argomento. – hartz89
Quindi, prova a usare direttamente 'send' per' clientOutboundChannel' da '@ MessageExceptionHandler'. –
@ArtemBilan potresti spiegare come ottenere OutboundChannel? Fatto una domanda: http://stackoverflow.com/questions/39641477/send-stomp-error-from-spring-websocket-program –