サーバーがユーザー権限に基づいて特定のトピックのトピックサブスクリプションを拒否できるバージョンのストックアプリケーションを実装しています。これを行う方法はspring-websocketにありますか?
例えば:
株式サンプルプロジェクトでは、Apple、Microsoft、Googleの3つの商品の価格トピックがあり、User1、User2の2人のユーザーがいます。
User1はAppleにアクセスでき、MicrosoftUser2はGoogleにのみアクセスできる必要があります
User1がGoogleにサブスクライブしている場合、応答は拒否され、その後メッセージがブロードキャストされないようにする必要があります。
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;
}
}
Spring 5.xの時点で、インターセプターをアタッチするためにオーバーライドする正しいメソッドは、AbstractSecurityWebSocketMessageBrokerConfigurer
を拡張している場合、customizeClientInboundChannel
です。
@Override public void customizeClientInboundChannel(ChannelRegistration registration) { registration.interceptors(new TopicSubscriptionInterceptor()); }