2015-11-16 12 views
12

Tam özellikli bir ActiveMQ aracıyla Spring'in STOMP'unu WebSocket uygulaması üzerinden kullanıyorum. Bir konu için kullanıcılar SUBSCRIBE, başarılı bir şekilde abone olmadan önce geçmesi gereken bazı izinler mantığı vardır. Aşağıda yapılandırılan gibi ben izinler mantığını uygulamak için bir ChannelInterceptor kullanıyorum:Bahar WebSocket ile STOMP istemcilerine HATA iletisi nasıl gönderilir?

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

Yeterli izinleri olmayan istemciler kısıtlanmış bir konuya abone olmaya çalıştığında, aslında BUT konusundaki hiçbir iletiyi almazlar, ayrıca aboneliklerini reddeden istisna hakkında bilgilendirilmezler. Bunun yerine, istemci ActiveMQ aracısının hiçbir şey bilmediği ölü bir abonelik geri veriyor.

benim Java testi müşteri ile users/queue/errors sadece düz başarıyla bağlandıktan sonra users/{subscribingUsername}/queue/errors abone ve denedim (beklendiği gibi normal, yeterince-izinli istemci STOMP son nokta ile etkileşimleri ve konular. Sadece çalışmak), ama şimdiye kadar var İstemciye gönderilen sunucudan gelen abonelik istisnasıyla ilgili hata mesajını alamadı. Bu, istemcilerin erişim reddedildikleri konusunda hiçbir zaman haberdar olmadıklarından, ideal olarak daha azdır.

cevap

5

Sen sonuncusu ExecutorSubscribableChannel çünkü sadece, clientInboundChannel üzerinde MySubscriptionInterceptor den istisna dolayısıyla async ve bu ipliklerden herhangi bir istisna arayana herhangi yeniden atışla günlüklerinde sona edilir olamaz - StompSubProtocolHandler.handleMessageFromClient .

Fakat orada clientOutboundChannel gibi bir şey ve bu gibi kullanmak ne yapabilirim:

StompHeaderAccessor headerAccessor = StompHeaderAccessor.create(StompCommand.ERROR); 
headerAccessor.setMessage(error.getMessage()); 

clientOutboundChannel.send(MessageBuilder.createMessage(new byte[0], headerAccessor.getMessageHeaders())); 

Başka bir seçenek dikkate almak Ek Açıklama haritalama şudur: Bu @Artem için

@SubscribeMapping("/foo") 
    public void handleWithError() { 
     throw new IllegalArgumentException("Bad input"); 
    } 

    @MessageExceptionHandler 
    @SendToUser("/queue/error") 
    public String handleException(IllegalArgumentException ex) { 
     return "Got error: " + ex.getMessage(); 
    } 
+0

sayesinde bunu verdi bir deneme. Ne yazık ki, @ AboneMapping' yönteminde bir istisna atıldığında ve '@ MessageExceptionHandler' yöntemiyle işlendiğinde, istemcinin hata sırasına bir ileti gönderilir, AMA aboneliği hala aracıya yönlendirilir ve istemci yine de sonraki iletileri alır. konudan. – hartz89

+1

Yani, '' Message' 'mesajını' 'MessageExceptionHandler''dan' clientOutboundChannel' için kullanmaya çalışın. –

+0

@ArtemBilan, OutboundChannel'i nasıl alacağınızı açıklayabilir misiniz? Bir soru sordu: http://stackoverflow.com/questions/39641477/send-stomp-error-from-spring-websocket-program –