提问者:小点点

不带主体的Springwebsocket


我正在尝试实现一个简单的websocket应用程序,可以从一个endpoint发送消息到其他地方建立的指定会话。到目前为止,我已经能够使用注释@SendToUser()以便客户端订阅频道(如本问题所述:Spring Websockets@SendToUser无需登录?)

但是,我现在想要创建一个单独的endpoint,当调用该endpoint时,它会查找与传递到该endpoint的数据相关联的用户,并向该用户发送有关此数据的消息。

但是,我无法准确确定如何制作它,以便我可以调用SimpMessagingTemplate转换AndSendToUser()命令,因为我的用户没有主体(我没有使用Spring Security)。

我已经能够将MessageHeaders中的simpSessionId传递到@MessageMapsendpoint,但现在我不知道如何使用simpSessionId从应用程序的不同部分发送信息。

我已经做了一些研究,关于覆盖DefaultHandshakeHandler的确定用户()方法,并在成功的websocket握手后为用户分配一个随机生成的UUID作为用户名(如这个问题的答案所述:如何在Spring 4 STOMP over WebSocket配置中回复未经身份验证的用户?),但是由于即将出现的主体为空,我不确定如何正确生成一个并将其分配给主体以用于应用程序。

我基本上需要拥有匿名用户并在他们创建websocket连接后从应用程序的不同部分向他们发送消息的能力。


共1个答案

匿名用户

因此,对于其他面临类似问题的人,我实现了自己的校长课程:

package hello;

import java.security.Principal;
import java.util.Objects;

public class AnonymousPrincipal implements Principal {

    private String name;

    @Override
    public String getName() {
        // TODO Auto-generated method stub
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object another) {
        if (!(another instanceof Principal))
            return false;

        Principal principal = (Principal) another;
        return principal.getName() == this.name;

    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}

然后,我实现了我自己版本的DefaultHandshakeHandler:

package hello;

import java.security.Principal;
import java.util.Map;
import java.util.UUID;

import org.springframework.http.server.ServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;

public class CustomHandshakeHandler extends DefaultHandshakeHandler {

    @Override
    protected Principal determineUser(ServerHttpRequest request,
            WebSocketHandler wsHandler, Map<String, Object> attributes) {
        Principal principal = request.getPrincipal();           

        if (principal == null) {
            principal = new AnonymousPrincipal();

            String uniqueName = UUID.randomUUID().toString();

            ((AnonymousPrincipal) principal).setName(uniqueName);
        }

        return principal;

    }

}

现在,当握手发生时,websocket会话会得到分配给它的这个主体,所以如果用户是匿名的,他们会得到一个分配的匿名主体,这将允许我存储他们的名字(生成的UUID),以便以后在应用程序的其他部分使用。