简体   繁体   English

@MessageMapping 不适用于 Spring Security 和 MVC

[英]@MessageMapping does not work with Spring Security and MVC

I have an application that uses Spring MVC and Security.And I try to add Websockets to it.我有一个使用 Spring MVC 和 Security 的应用程序。我尝试向其中添加 Websocket。 I already have successful connection but, when i try to send message to backend - nothing happends.我已经成功连接但是,当我尝试向后端发送消息时 - 什么也没发生。 In debug mode method annotated with @MessageMapping does not reach at all!在调试模式下用@MessageMapping 注释的方法根本达不到! And I don know why.我不知道为什么。 I have already tried a lot of Google solutions, so for now all configurations are next:我已经尝试了很多谷歌解决方案,所以现在所有的配置都是下一个:

@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();
    }
}

Also I have added security config for websockets我还为 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 class控制器类

@Controller
public class WebsocketController {

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

    }
}

socket.js, that is importing to JSP file 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 (further is importing to main spring.xml) 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>

browser log:浏览器日志:

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"}

Do somebody know what am I doing wrong?有人知道我做错了什么吗?

EDITION 1 By the way, when I use this configs in simple project, without Spring-Security everything works perfectly!版本 1顺便说一句,当我在简单的项目中使用这个配置时,没有 Spring-Security 一切正常!

So, i found the solution!所以,我找到了解决方案! The mistake was very simple.错误非常简单。 My WebSocketConfig was initialized by IoC context, not MVC .我的WebSocketConfig是由IoC上下文初始化的,而不是MVC I moved it to package that was scanned by MVC context and all started work perfectly!我将它移到由 MVC 上下文扫描的包中,并且一切都开始完美运行! If somebody has same situation be sure, that you web socket config class is initializing by MVC context.如果有人有相同的情况,请确保您的 Web 套接字配置类正在由 MVC 上下文初始化。

I had a similar issue.我有一个类似的问题。

I had to move my class that had @EnableWebMvc from getRootConfigClasses() to getServletConfigClasses() in my initialiser that extends AbstractAnnotationConfigDispatcherServletInitializer.我不得不在扩展 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[] { "/" };
   }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM