如何防止订阅spring socket / queue / private / * destination。

问题描述 投票:1回答:2

我有一个Java套接字API应用程序,它处理来自用户的套接字请求并发送响应。我有一个配置器:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
    private static final Logger LOGGER = Logger.getLogger(WebSocketConfig.class);
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/queue");
        config.setApplicationDestinationPrefixes("/server_in");
        config.setUserDestinationPrefix("/user");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/websocket").withSockJS();
    }
}

当我向用户发送回复时,我会执行以下操作:this.simpMessagingTemplate.convertAndSend("/queue/private/user_"+secret_key, socketResponse);

在客户端上我有以下代码:

   sc.subscribe('/queue/private/user_'+secret_key, function (greeting) {
        console.log(greeting.body);
    });

响应处理成功。但问题是其他一些用户也可以订阅“/ queue / private / *”目的地并处理私人消息。

   sc.subscribe('/queue/private/*', function (greeting) {
        console.log(greeting.body);
    });

我该如何防止这种行为?

java spring sockets
2个回答
3
投票

如果您希望每个用户都有一个套接字并且只向他发送消息,那么您可以做的是:

像对待endPoint一样订阅,但例如使用“/ user”infront

sc.subscribe('/user/queue/websocket, function (greeting) {
    console.log(greeting.body);
});

在服务器端你应该有一个休息方法:

@RequestMapping(value = "/test", method = RequestMethod.POST)
public void test(Principal principal) throws Exception {
    this.template.convertAndSendToUser(principal.getName(), "/queue/click", "");
}

有了这个,每个用户都会收到每个频道的用户,并且只有用户会在进行休息呼叫时收到通知。

其余的调用应该进行身份验证,以便Principal拥有用户名。

用户通道是从Spring自动管理的,因此您必须像这样添加它。


0
投票

您可以扩展ChannelInterceptorAdapter并单独管理每个事件:

public class AuthorizedChannelInterceptorAdapter extends ChannelInterceptorAdapter {
    @Override
    public Message<?> preSend(Message<?> message, MessageChannel messageChannel) throws AuthenticationException {
        StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
        if (StompCommand.CONNECT == accessor.getCommand())
            setUserAuthenticationToken(accessor);
        else if (StompCommand.SUBSCRIBE == accessor.getCommand())
            validateSubscription((Authentication) accessor.getUser(), accessor.getDestination());
        return message;
    }

    private void setUserAuthenticationToken(StompHeaderAccessor accessor) {
        String token = accessor.getFirstNativeHeader(HttpHeaders.AUTHORIZATION);
        accessor.setUser(loadAuthentication(token));
    }

    private Authentication loadAuthentication(String token){
        return ....;
    }

    private void validateSubscription(Authentication authentication, String destination) {
        if(...)
           throw new AccessDeniedException("No permission to subscribe to this topic");
    }
}

首先,您需要在连接事件中存储客户端提供的身份验证对象。在此之后,客户端发送的每个事件都将设置此身份验证对象,以便您可以使用它来验证是否有权订阅特定通道。

© www.soinside.com 2019 - 2024. All rights reserved.