@MessageMapping与Spring Security和MVC不兼容

3

我有一个使用Spring MVC和Security的应用程序。我尝试在其中添加Websockets。我已经成功建立连接,但是当我尝试向后端发送消息时,没有任何反应。在调试模式下,用@MessageMapping注释的方法根本没有被执行!我不知道为什么。我已经尝试了很多谷歌的解决方案,所以现在所有的配置如下:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    public WebSocketConfig() {
    }

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

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

我已经为 WebSockets 添加了安全性配置。
@Configuration
public class SecuritySocketConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {

    protected boolean sameOriginDisabled() {
        return true;
    }

    protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
        messages.simpDestMatchers("/hello1").authenticated().simpDestMatchers("/app/hello1").authenticated();//permitAll();

    }
} 

控制器类

@Controller
public class WebsocketController {

    @MessageMapping("/hello1")
    public void send(Message message) {
        String name = message.getName();

    }
}

socket.js,它被导入到JSP文件中

;(function () {

    //init
    $(function () {
        $("#control_mode").change(app.page.controlCheck);
        connect();
    });
    var stompClient = null;


    function connect() {
        var socket = new SockJS("http://localhost:8080/hello1");
        stompClient = Stomp.over(socket);
        console.log('attempt to connect: ' +stompClient!=null);
        console.log('session id: '+ "${pageContext.session.id}");

        stompClient.connect('', '', function(frame) {
            console.log('Connected: ' + frame);
            stompClient.subscribe('/topic/greetings/', function(result) {
                getResult(result);
            });

        });
    }

    function getResult(result) {
       var isControlable= JSON.parse(greeting.body).isControlable;
        if (isControlable) {
            alert('Control was already gained')
        } else {
            $("#control_mode").prop("checked", true);
        }
    }

    app.page.controlCheck = function () {
        stompClient.send('/app/hello1', {}, JSON.stringify({'name' : "alastor" }));
        if (this.checked) {
            $("#control_mode").prop("checked", !this.checked);
        } else {
            alert('was click for release control');
        }
    };

    function disconnect() {
        stompClient.disconnect();
        console.log("Disconnected");
    }
})();

spring-security.xml(进一步导入到主spring.xml中)

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns="http://www.springframework.org/schema/security"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security.xsd">

    <http pattern="/resources/**" security="none"/>
    <http pattern="/webjars/**" security="none"/>
    <http pattern="/rest/**" security="none"/>
    <http pattern="/favicon.ico" security="none"/>

    <http security="none" pattern="/pathWhereCSRFWillBeIgnored/**"/>
    <http>
        <intercept-url pattern="/welcome/**" access="permitAll"/>
        <intercept-url pattern="/ajax/welcome/**" access="permitAll"/>
        <intercept-url pattern="/ajax/**" access="permitAll"/>  <!--todo for testing-->

        <intercept-url pattern="/**" access="@validateService.isValid(request)"/>
        <form-login login-page="/welcome"
                    authentication-failure-url="/welcome?error=true"
                    login-processing-url="/spring_security_check"
                    authentication-success-handler-ref="directLinkHandler"/>
        <logout logout-success-url="/welcome"/>
        <csrf disabled="true"/>
    </http>

    <beans:bean class="com.promptlink.stbtp.webapi.listener.AuthenticationEventListener"/>

    <beans:bean class="com.promptlink.stbtp.service.security.util.PasswordEncoder" id="passwordEncoder"/>

    <authentication-manager alias="authenticationManager">
        <authentication-provider user-service-ref="userService">
            <password-encoder ref="passwordEncoder"/>
        </authentication-provider>
    </authentication-manager>
</beans:beans>

浏览器日志:

Opening Web Socket... stomp.js:134:99
Web Socket Opened... stomp.js:134:99
>>> CONNECT
login:
passcode:
accept-version:1.1,1.0
heart-beat:10000,10000

 stomp.js:134:99
<<< CONNECTED
version:1.1
heart-beat:0,0
user-name:qwe

 stomp.js:134:99
connected to server undefined stomp.js:134:99
Connected: CONNECTED
user-name:qwe
heart-beat:0,0
version:1.1

 socket.js:18:13
>>> SUBSCRIBE
id:sub-0
destination:/topic/greetings/

 stomp.js:134:99
>>> SEND
destination:/app/hello1
content-length:18

{"name":"alastor"}

有人知道我做错了什么吗?

版本1 顺便说一下,当我在没有Spring-Security的简单项目中使用这些配置时,一切都运行得很完美!

2个回答

5
所以,我找到了解决方案!错误非常简单。我的WebSocketConfig是由IoC上下文初始化的,而不是MVC。我将它移动到被MVC上下文扫描的包中,一切都开始完美地工作了!如果有人遇到同样的情况,请确保您的WebSocket配置类是由MVC上下文初始化的。

你好,我跟你有一样的问题,你说的"WebSocketConfig was initialized by IoC context, not MVC"是什么意思? - user1434702
这正是我的问题。在我的测试用例配置中,我的 WebSocketConfig 没有被组件扫描捕获(将 @ComponentScan 注解添加到我的测试配置中即可解决)。 - Justin Albano

2

我曾经也遇到过类似的问题。

在继承了AbstractAnnotationConfigDispatcherServletInitializer的初始化器中,我不得不将带有@EnableWebMvc的类从getRootConfigClasses()移动到getServletConfigClasses()中。

public class MyAppInitiser extends AbstractAnnotationConfigDispatcherServletInitializer {

   @Override
   protected Class<?>[] getRootConfigClasses() {
       return new Class[] { TaskSchedulerConfig.class, 
               AsyncConfig.class , WebSecurityConfig.class };
   }
   /* WebMvcConfig contains @EnableWebMvc */
   @Override
   protected Class<?>[] getServletConfigClasses() {
      return new Class[] {WebSocketConfig.class ,  WebMvcConfig.class};
   }

   @Override
   protected String[] getServletMappings() {
      return new String[] { "/" };
   }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接