Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用SpringWebSocket拒绝基于用户权限的主题订阅_Spring_Spring Security_Websocket_Publish Subscribe_Spring Websocket - Fatal编程技术网

如何使用SpringWebSocket拒绝基于用户权限的主题订阅

如何使用SpringWebSocket拒绝基于用户权限的主题订阅,spring,spring-security,websocket,publish-subscribe,spring-websocket,Spring,Spring Security,Websocket,Publish Subscribe,Spring Websocket,我正在实现一个stock应用程序的版本,其中服务器能够根据用户权限拒绝特定主题的主题订阅。 在SpringWebSocket中有什么方法可以做到这一点吗 例如: 在股票示例项目中,我们有3种工具的价格主题:苹果、微软、谷歌 并且有两个用户:User1,User2 User1应该可以访问苹果和微软 User2应该只能访问Google 如果用户1订阅了谷歌,他应该会收到拒绝的回复,之后消息不应该向他广播。多亏了Rossen Stoyanchev,我通过向入站频道添加拦截器成功地解决了这个问题。演示应

我正在实现一个stock应用程序的版本,其中服务器能够根据用户权限拒绝特定主题的主题订阅。 在SpringWebSocket中有什么方法可以做到这一点吗

例如:

在股票示例项目中,我们有3种工具的价格主题:苹果、微软、谷歌 并且有两个用户:User1,User2

User1应该可以访问苹果和微软 User2应该只能访问Google


如果用户1订阅了谷歌,他应该会收到拒绝的回复,之后消息不应该向他广播。

多亏了Rossen Stoyanchev,我通过向入站频道添加拦截器成功地解决了这个问题。演示应用程序中需要的更改如下:

更改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;
}
公共类TopicSubscriptionInterceptor扩展了ChannelInterceptor适配器{
私有静态记录器Logger=org.slf4j.LoggerFactory.getLogger(TopicSubscriptionInterceptor.class);
@凌驾
公共消息呈现(消息消息、消息通道){
StompHeaderAccessor headerAccessor=StompHeaderAccessor.wrap(消息);
if(StompCommand.SUBSCRIBE.equals(headerAccessor.getCommand())){
Principal userPrincipal=headerAccessor.getUser();
如果(!validateSubscription(userPrincipal,headerAccessor.getDestination()))
{
抛出新的IllegalArgumentException(“不允许此主题”);
}
}
返回消息;
}
私有布尔验证订阅(主体,字符串主题目标)
{
if(principal==null){
//未经验证的用户
返回false;
}
debug(“验证{}对主题{},principal.getName(),topicDestination的订阅”);
//这里有额外的验证逻辑
返回true;
}

}

从Spring 5.x开始,如果您正在扩展
AbstractSecurityWebSocketMessageBrokerConfigure
,则覆盖以附加拦截器的正确方法是
customizeClientInboundChannel

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

您好,我正在使用SpringWebSocket,与您面临类似的情况。你能告诉我调用headerAccessor.getHeader(“simpUser”)时的值在哪里吗。WebSockeThttpHeader只能在client-side.org.springframework.messaging.MessagingException中为头添加字符串值