如何为 spring 5 websocket 添加安全性

gst*_*low 7 java spring spring-security websocket spring-boot

我遵循以下教程:使用 WebSocket 构建交互式 Web 应用程序

一切都按照描述进行,并且应用程序看起来很好。我只有一个很好的控制器:

@Controller
public class GreetingController {    

    @MessageMapping("/hello")
    @SendTo("/topic/greetings")
    public Greeting greeting(HelloMessage message) throws Exception {
        Thread.sleep(1000); // simulated delay
        return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");
    }

}
Run Code Online (Sandbox Code Playgroud)

还有一点配置。

现在我想为这个简单的应用程序添加安全性。我花了时间找例子,但找不到。

一般来说,我找到了教程:

预览 Spring Security WebSocket 支持

但看起来这个例子只与 spring 4 相关,而不是 spring 5。而且我不明白我应该在哪里提供凭据等。描述不够详细,无法应用于我的示例。

我发现了另外一个教程: Websocket Authentication and Authorization in Spring Ask

它看起来更清晰,但我不确定它是目前最好的解决方案。

您能建议为我的应用程序配置 spring security 的最简单方法吗?

PS我还发现了不一样但熟悉的问题How to secure websocket application [Spring boot + STOMP],但目前没有答案。

locus2k的更新

现在我有以下配置:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
    private static String[] authorities = new String[]{
            "VIEW_SCRIPT_TAB", "VIEW_CREDS_TAB"
    };

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry
                .addEndpoint("/gs-guide-websocket")
                .addInterceptors(new HandshakeInterceptor() {
                    @Override
                    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
                        System.out.println("Handshake interceptor beforeHandshake");
                        return true;
                    }

                    @Override
                    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, @Nullable Exception exception) {
                        System.out.println("Handshake interceptor after");
                    }
                })
                .withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/topic");
        registry.setApplicationDestinationPrefixes("/app");
    }

    @Override
    protected void configureInbound(MessageSecurityMetadataSourceRegistry message) {

        message
                .nullDestMatcher().permitAll()
                .simpDestMatchers("/app/**").hasAnyAuthority(authorities)
                .simpSubscribeDestMatchers("/topic/**").permitAll()
                .anyMessage().denyAll();
    }
}
Run Code Online (Sandbox Code Playgroud)

当我启动应用程序时,我看到堆栈跟踪:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'stompWebSocketHandlerMapping' defined in class path resource [org/springframework/web/socket/config/annotation/DelegatingWebSocketMessageBrokerConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'stompWebSocketHandlerMapping' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'subProtocolWebSocketHandler' defined in class path resource [org/springframework/web/socket/config/annotation/DelegatingWebSocketMessageBrokerConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.socket.WebSocketHandler]: Factory method 'subProtocolWebSocketHandler' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientInboundChannel' defined in class path resource [org/springframework/web/socket/config/annotation/DelegatingWebSocketMessageBrokerConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.messaging.support.AbstractSubscribableChannel]: Factory method 'clientInboundChannel' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientInboundChannelExecutor' defined in class path resource [org/springframework/web/socket/config/annotation/DelegatingWebSocketMessageBrokerConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor]: Factory method 'clientInboundChannelExecutor' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'inboundChannelSecurity' defined in class path resource [com/my/ws/example/ws_example/hello/WebSocketConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor]: Factory method 'inboundChannelSecurity' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'inboundMessageSecurityMetadataSource' defined in class path resource [com/my/ws/example/ws_example/hello/WebSocketConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.messaging.access.intercept.MessageSecurityMetadataSource]: Factory method 'inboundMessageSecurityMetadataSource' threw exception; nested exception is java.lang.NoSuchMethodError: org.springframework.security.messaging.access.expression.ExpressionBasedMessageSecurityMetadataSourceFactory.createExpressionMessageMetadataSource(Ljava/util/LinkedHashMap;Lorg/springframework/security/access/expression/SecurityExpressionHandler;)Lorg/springframework/security/messaging/access/intercept/MessageSecurityMetadataSource;
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:587) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    ....
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'stompWebSocketHandlerMapping' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'subProtocolWebSocketHandler' defined in class path resource [org/springframework/web/socket/config/annotation/DelegatingWebSocketMessageBrokerConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.socket.WebSocketHandler]: Factory method 'subProtocolWebSocketHandler' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientInboundChannel' defined in class path resource [org/springframework/web/socket/config/annotation/DelegatingWebSocketMessageBrokerConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.messaging.support.AbstractSubscribableChannel]: Factory method 'clientInboundChannel' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientInboundChannelExecutor' defined in class path resource [org/springframework/web/socket/config/annotation/DelegatingWebSocketMessageBrokerConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor]: Factory method 'clientInboundChannelExecutor' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'inboundChannelSecurity' defined in class path resource [com/my/ws/example/ws_example/hello/WebSocketConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor]: Factory method 'inboundChannelSecurity' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'inboundMessageSecurityMetadataSource' defined in class path resource [com/my/ws/example/ws_example/hello/WebSocketConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.messaging.access.intercept.MessageSecurityMetadataSource]: Factory method 'inboundMessageSecurityMetadataSource' threw exception; nested exception is java.lang.NoSuchMethodError: org.springframework.security.messaging.access.expression.ExpressionBasedMessageSecurityMetadataSourceFactory.createExpressionMessageMetadataSource(Ljava/util/LinkedHashMap;Lorg/springframework/security/access/expression/SecurityExpressionHandler;)Lorg/springframework/security/messaging/access/intercept/MessageSecurityMetadataSource;
    ... 18 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'subProtocolWebSocketHandler' defined in class path resource [org/springframework/web/socket/config/annotation/DelegatingWebSocketMessageBrokerConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.socket.WebSocketHandler]: Factory method 'subProtocolWebSocketHandler' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientInboundChannel' defined in class path resource [org/springframework/web/socket/config/annotation/DelegatingWebSocketMessageBrokerConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.messaging.support.AbstractSubscribableChannel]: Factory method 'clientInboundChannel' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientInboundChannelExecutor' defined in class path resource [org/springframework/web/socket/config/annotation/DelegatingWebSocketMessageBrokerConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor]: Factory method 'clientInboundChannelExecutor' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'inboundChannelSecurity' defined in class path resource [com/my/ws/example/ws_example/hello/WebSocketConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor]: Factory method 'inboundChannelSecurity' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'inboundMessageSecurityMetadataSource' defined in class path resource [com/my/ws/example/ws_example/hello/WebSocketConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.messaging.access.intercept.MessageSecurityMetadataSource]: Factory method 'inboundMessageSecurityMetadataSource' threw exception; nested exception is java.lang.NoSuchMethodError: org.springframework.security.messaging.access.expression.ExpressionBasedMessageSecurityMetadataSourceFactory.createExpressionMessageMetadataSource(Ljava/util/LinkedHashMap;Lorg/springframework/security/access/expression/SecurityExpressionHandler;)Lorg/springframework/security/messaging/access/intercept/MessageSecurityMetadataSource;
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:587) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]    
    ... 19 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.socket.WebSocketHandler]: Factory method 'subProtocolWebSocketHandler' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientInboundChannel' defined in class path resource [org/springframework/web/socket/config/annotation/DelegatingWebSocketMessageBrokerConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.messaging.support.AbstractSubscribableChannel]: Factory method 'clientInboundChannel' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientInboundChannelExecutor' defined in class path resource [org/springframework/web/socket/config/annotation/DelegatingWebSocketMessageBrokerConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor]: Factory method 'clientInboundChannelExecutor' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'inboundChannelSecurity' defined in class path resource [com/my/ws/example/ws_example/hello/WebSocketConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor]: Factory method 'inboundChannelSecurity' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'inboundMessageSecurityMetadataSource' defined in class path resource [com/my/ws/example/ws_example/hello/WebSocketConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.messaging.access.intercept.MessageSecurityMetadataSource]: Factory method 'inboundMessageSecurityMetadataSource' threw exception; nested exception is java.lang.NoSuchMethodError: org.springframework.security.messaging.access.expression.ExpressionBasedMessageSecurityMetadataSourceFactory.createExpressionMessageMetadataSource(Ljava/util/LinkedHashMap;Lorg/springframework/security/access/expression/SecurityExpressionHandler;)Lorg/springframework/security/messaging/access/intercept/MessageSecurityMetadataSource;
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    ... 41 common frames omitted
....
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor]: Factory method 'inboundChannelSecurity' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'inboundMessageSecurityMetadataSource' defined in class path resource [com/my/ws/example/ws_example/hello/WebSocketConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.messaging.access.intercept.MessageSecurityMetadataSource]: Factory method 'inboundMessageSecurityMetadataSource' threw exception; nested exception is java.lang.NoSuchMethodError: org.springframework.security.messaging.access.expression.ExpressionBasedMessageSecurityMetadataSourceFactory.createExpressionMessageMetadataSource(Ljava/util/LinkedHashMap;Lorg/springframework/security/access/expression/SecurityExpressionHandler;)Lorg/springframework/security/messaging/access/intercept/MessageSecurityMetadataSource;
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    ... 113 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'inboundMessageSecurityMetadataSource' defined in class path resource [com/my/ws/example/ws_example/hello/WebSocketConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.messaging.access.intercept.MessageSecurityMetadataSource]: Factory method 'inboundMessageSecurityMetadataSource' threw exception; nested exception is java.lang.NoSuchMethodError: org.springframework.security.messaging.access.expression.ExpressionBasedMessageSecurityMetadataSourceFactory.createExpressionMessageMetadataSource(Ljava/util/LinkedHashMap;Lorg/springframework/security/access/expression/SecurityExpressionHandler;)Lorg/springframework/security/messaging/access/intercept/MessageSecurityMetadataSource;
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:587) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    ... 114 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.messaging.access.intercept.MessageSecurityMetadataSource]: Factory method 'inboundMessageSecurityMetadataSource' threw exception; nested exception is java.lang.NoSuchMethodError: org.springframework.security.messaging.access.expression.ExpressionBasedMessageSecurityMetadataSourceFactory.createExpressionMessageMetadataSource(Ljava/util/LinkedHashMap;Lorg/springframework/security/access/expression/SecurityExpressionHandler;)Lorg/springframework/security/messaging/access/intercept/MessageSecurityMetadataSource;
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    ... 136 common frames omitted
Caused by: java.lang.NoSuchMethodError: org.springframework.security.messaging.access.expression.ExpressionBasedMessageSecurityMetadataSourceFactory.createExpressionMessageMetadataSource(Ljava/util/LinkedHashMap;Lorg/springframework/security/acces

gst*_*low 2

提供与不兼容的库版本相关的堆栈跟踪。

如果使用正确的依赖项,它会起作用。例如:

compile ('org.springframework.security:spring-security-messaging:5.0.4.RELEASE')
compile ('org.springframework.security:spring-security-web: 5.0.4.RELEASE')
Run Code Online (Sandbox Code Playgroud)