2015-11-16 8 views
12

私は、フル機能のActiveMQブローカでWebSocket実装のSpringのSTOMPを使用しています。トピックへのユーザーSUBSCRIBEの場合、正常に購読される前に通過しなければならないいくつかの許可ロジックがあります。以下に構成された私は、権限のロジックを適用するChannelInterceptorを使用しています:Spring WebSocketを使用してSTOMPクライアントにERRORメッセージを送信するには?

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

制限付きトピックの購読を試みるクライアントは、トピックからのメッセージを実際に受け取ることはありませんが、サブスクリプションを拒否した例外は通知されません。代わりに、クライアントは、ActiveMQブローカーが何も知らないデッドサブスクリプションを手渡されます。

正常に接続された後、私はusers/{subscribingUsername}/queue/errorsに登録して、users/queue/errorsをJavaテストクライアントでプレーングしてみましたが、これまでのところ、私はこれを持っていますクライアントに配信されたサーバーからのサブスクリプション例外に関するエラーメッセージの一種を取得できませんでした。アクセスが拒否されたことがクライアントに通知されることはないので、明らかに理想的ではありません。

答えて

5

最後のものは、それゆえ、ExecutorSubscribableChannelあるので、あなたはただ、clientInboundChannelMySubscriptionInterceptorから例外をスローすることはできませんがasyncで、それらのスレッドからのすべての例外は、呼び出し側への再スローとログに終わるされている - StompSubProtocolHandler.handleMessageFromClientを。

しかし、あなたが行うことができますclientOutboundChannelのようなものがあると、このようにそれを使用します。考慮すべき

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

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

別のオプションは、注釈マッピングです:この@Artemため

@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

おかげで、私はそれを与えました試してみる。残念ながら、 '@ SubscribeMapping'メソッドで例外がスローされ、' @ MessageExceptionHandler'メソッドで処理されると、メッセージISはクライアントのエラーキューに送られますが、サブスクリプションは依然としてブローカに転送され、クライアントは引き続きメッセージを受け取りますトピックから。 – hartz89

+1

そのため、 '@ MessageExceptionHandler'から' clientOutboundChannel'に直接 'send'を使ってみてください。 –

+0

@ArtemBilan OutboundChannelの入手方法を教えてください。質問をしました:http://stackoverflow.com/questions/39641477/send-stomp-error-from-spring-websocket-program –

関連する問題