我正在尝试实现一个简单的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连接后从应用程序的不同部分向他们发送消息的能力。
因此,对于其他面临类似问题的人,我实现了自己的校长课程:
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),以便以后在应用程序的其他部分使用。