【问题标题】:Spring websocket MissingSessionUserException: No "user" header in messageSpring websocket MissingSessionUserException:消息中没有“用户”标头
【发布时间】:2016-04-14 07:15:03
【问题描述】:

当我尝试在 Spring websocket 上从客户端向服务器发送消息时遇到问题。 我在服务器上配置 Websocket 并在控制器上创建 @Message。 我通过javascript从客户端发送数据。 它有时只是工作,但有时它会失败并在服务器上抛出消息:MissingSessionUserException: No "user" header in message

这是我的 WebsocketConfig:

public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/connectsocket").withSockJS();
    }
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/");
    }
}

这是我的 MessageController:

@RestController
public class MessageController {

    @Autowired
    private SimpMessagingTemplate template;

    @MessageMapping("/websocket/message")
    public synchronized void message(Message<Object> messageObj, 
        WebMessage message, Principal principal) throws Exception {
        if (principal != null) {
            String name = principal.getName();
            template.convertAndSendToUser(name, "/topic/dynamic", new MessagePojo("stage", "value", "message"));
        }
    }
}

这是我的 Javascript-backbonejs 代码:

app.Models.WebsocketModel = Backbone.Model.extend({
    fetchData : function() {
        console.log("WebsocketModel: fetchData");
        var socket = new SockJS(url + "/connectsocket");
        var client = Stomp.over(socket);

        var onConnect = function(frame) {
            console.log('Connected: ' + frame);
            client.subscribe("/user/topic/dynamic", function(data) {
                var jsonBody = JSON.parse(data.body);
                console.log(jsonBody);
            });
        };

        client.connect({}, onConnect);

        setInterval(function() {
            client.send("/websocket/message", {}, JSON.stringify({
                "message" : "Hello world!!!",
                "toUser" : "Someone"
            }));
        }, 10000);
    }
});

这是我的服务器错误日志:

[2016 年 4 月 14 日 - 02:13:19] 错误: [org.springframework.web.socket.messaging.WebSocketAnnotationMethodMessageHandler] - 未处理的异常 org.springframework.messaging.simp.annotation.support.MissingSessionUserException: 消息中没有“用户”标头 org.springframework.messaging.simp.annotation.support.PrincipalMethodArgumentResolver.resolveArgument(PrincipalMethodArgumentResolver.java:42) 在 org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77) 在 org.springframework.messaging.handler.invocation.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:139) 在 org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:108) 在 org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMatch(AbstractMethodMessageHandler.java:490) 在 org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:497) 在 org.springframework.messaging.simp.annotation.support.SimpAnnotationMethodMessageHandler.handleMatch(SimpAnnotationMethodMessageHandler.java:87) 在 org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessageInternal(AbstractMethodMessageHandler.java:451) 在 org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(AbstractMethodMessageHandler.java:389) 在 org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:135) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 在 java.lang.Thread.run(Thread.java:745)

【问题讨论】:

    标签: backbone.js websocket stomp spring-websocket


    【解决方案1】:

    您正在尝试订阅user destination,因此必须对用户进行身份验证。

    如果是匿名用户想要订阅该主题,answer to this question 会有所帮助。

    您必须为用户分配一个匿名身份,有两种选择:

    1. 配置DefaultHandshakeHandler 的子类,覆盖determineUser 并为每个WebSocketSession 分配某种身份。

    2. WebSocket 会话将依赖于在握手 HTTP 请求中从 HttpServletRequest.getUserPrincipal 返回的值。您可以让 servlet Filter 包装 HttpServletRequest 并决定从该方法返回什么。或者,如果您使用的是具有 AnonymousAuthenticationFilter 的 Spring Security,请覆盖其 createAuthentication 方法。

    【讨论】:

    • 感谢您的评论@Stanley。我很久以前就解决了我的问题,你的建议也是如此。这对像我这样的其他人会有帮助。过去,我在客户端发送到服务器之前检查了网络上的标头,然后我发现缺少用户身份验证。之后我只是在客户端发送到服务器之前添加用户身份验证,它工作正常。
    猜你喜欢
    • 2015-08-08
    • 1970-01-01
    • 1970-01-01
    • 2016-04-28
    • 1970-01-01
    • 1970-01-01
    • 2020-05-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多