web-dev-qa-db-ja.com

Spring-websocketでユーザー権限に基づいてトピックサブスクリプションを拒否する方法

サーバーがユーザー権限に基づいて特定のトピックのトピックサブスクリプションを拒否できるバージョンのストックアプリケーションを実装しています。これを行う方法はspring-websocketにありますか?

例えば:

株式サンプルプロジェクトでは、Apple、Microsoft、Googleの3つの商品の価格トピックがあり、User1、User2の2人のユーザーがいます。

User1はAppleにアクセスでき、MicrosoftUser2はGoogleにのみアクセスできる必要があります

User1がGoogleにサブスクライブしている場合、応答は拒否され、その後メッセージがブロードキャストされないようにする必要があります。

30
tomikiss

Rossen Stoyanchevのおかげで githubでの回答 インバウンドチャネルにインターセプターを追加することでこれを解決することができました。 spring-websocket-portfolio デモアプリケーションで必要な変更は次のとおりです。

WebSocket構成の変更:

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

そして、インターセプターは次のようなものでした。

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

}

44
tomikiss

Spring 5.xの時点で、インターセプターをアタッチするためにオーバーライドする正しいメソッドは、AbstractSecurityWebSocketMessageBrokerConfigurerを拡張している場合、customizeClientInboundChannelです。

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

2
Kermet