没有主体

时间:2017-04-04 22:17:44

标签: spring websocket stomp anonymous principal

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

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

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

我已经能够从传递给@MessageMapping端点的MessageHeaders获取simpSessionId,但现在我无法弄清楚如何使用simpSessionId从我的应用程序的不同部分发送信息。

我已经做了一些关于覆盖DefaultHandshakeHandler的determineUser()方法的研究,并在成功的websocket握手时将随机生成的UUID作为用户名分配给用户(如本问题的答案中所述:How to reply to unauthenticated user in Spring 4 STOMP over WebSocket configuration?) ,但由于主体即将出现,我不确定如何正确生成一个并将其分配给Principal以便与应用程序一起使用。

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

1 个答案:

答案 0 :(得分:3)

因此,对于遇到类似问题的其他人,我实施了自己的Principal类:

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)以供以后在其他部分使用。应用