如何使用Spring-websocket基于用户权限拒绝主题订阅

tom*_*iss 27 spring spring-security publish-subscribe websocket spring-websocket

我正在实现一个版本的股票应用程序,其中服务器能够根据用户权限拒绝特定主题的主题订阅.spring-websocket有没有办法做到这一点?

例如:

在库存示例项目中我们有3个仪器的价格主题:Apple,Microsoft,Google并且有两个用户:User1,User2

User1应该可以访问Apple,Microsoft User2应该只能访问Google

如果User1订阅Google,他应该被拒绝回复,之后不应该向他广播消息.

tom*_*iss 47

感谢Rosson Stoyanchev 在github上的回答, 我设法通过在入站通道中添加拦截器来解决这个问题.spring-websocket-portfolio演示应用程序所需的更改如下:

更改websocket配置:

public void configureClientInboundChannel(ChannelRegistration registration) {
    registration.setInterceptors(new TopicSubscriptionInterceptor());
}
Run Code Online (Sandbox Code Playgroud)

拦截器是这样的:

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;
}
Run Code Online (Sandbox Code Playgroud)

}

  • 您好,我正在使用弹簧websocket并面临与您类似的情况.你能告诉我调用headerAccessor.getHeader("simpUser")时的值是什么.WebsocketHttpHeaders只能在客户端为标头添加字符串值. (2认同)
  • 抛出 `org.springframework.messaging.MessagingException` 更好 (2认同)

小智 6

从 Spring 5.x 开始,如果要扩展,重写以附加拦截器的正确方法AbstractSecurityWebSocketMessageBrokerConfigurercustomizeClientInboundChannel

@Override
public void customizeClientInboundChannel(ChannelRegistration registration) {
    registration.interceptors(new TopicSubscriptionInterceptor());
}
Run Code Online (Sandbox Code Playgroud)