![](/img/trans.png)
[英]Spring messaging + security how to login throught websockets?
[英]Spring Websockets @SendToUser without login?
我有一个带有 websocket 功能的简单 spring 应用程序,到目前为止一切正常。 现在我想使用 @SendToUser 注释从我的服务器向特定客户端发送一条消息。 这给了我错误“忽略消息,没有可用的主要信息”。 我知道我的服务器上没有任何登录信息,因此每个用户都是“匿名的”并且没有主体(我现在不使用 spring 安全性)。 但是每个用户都有一个会话 ID。 是否可以以某种方式使用会话 ID 来区分用户? 我怎样才能做到这一点,以便我的用户获得与会话 ID 相对应的主体?
@SendToUser
使用@SendToUser
并在队列前添加“/user/”(仅限订阅者)。 休息有魔法:-)
代替
Java Server: @SendTo("/topic/showResult")
和
JS Client: stompClient.subscribe('/topic/showResult', function(calResult){ ....
用:
Java Server: @SentToUser("/topic/showResult")
和
JS Client: stompClient.subscribe('/user/topic/showResult', function(calResult){ ....
我认为一个解决方案可能是避免使用@SendToUser
并使用原始SimpMessagingTemplate
并将消息发送到您控制的打开会话的目标。
例如。 假设你有一个新的 websocket 会话的身份,你可以订阅一个队列名称中包含该标识符的队列:
stomp.subscribe("/queue/chats" + "-" + mycustomidentifier, onmessage);
现在,在 Spring websocket 侦听器端,您可以使用SimpMessagingTemplate
引导您的响应:
@Controller
public class MyController {
@Autowired
private SimpMessagingTemplate simpMessagingTemplate;
@MessageMapping("/chats")
public void handleChat(@Payload ChatMessage message) {
this.simpMessagingTemplate.convertAndSend("/queue/chats-" + "mycustomidentifier", "[" + getTimestamp() + "]:" + message.getMessage());
}
....
基于Biju 的回答并使用Stomp 生成的会话 ID (感谢mariusz2108 在他对类似问题的回答中),这对我有用(基于Spring 的规范示例)
SpringFramework 客户端:
private SimpMessagingTemplate template;
@Autowired
public GreetingController(SimpMessagingTemplate template) {
this.template = template;
}
@MessageMapping("/hello")
public void greeting(HelloMessage message, @Header("simpSessionId") String sessionId) throws Exception {
template.convertAndSend("/queue/greeting-"+sessionId, new Greeting("Hello, " + message.getName()));
}
JavaScript 客户端:
function connect() {
var socket = new SockJS('/gs-guide-websocket');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
var sessionId = /\/([^\/]+)\/websocket/.exec(socket._transport.url)[1];
console.log("connected, session id: " + sessionId);
stompClient.subscribe('/queue/greeting-'+sessionId, function (greeting) {
showGreeting(JSON.parse(greeting.body).content);
});
});
}
您可以使用 Web 容器的会话 ID(例如 JSESSIONID)代替 Stomp 会话 ID,但现在默认情况下无法从 JavaScript (对于 Tomcat)访问cookie,这是一个更困难的前景。
尝试这个。 它对我有用
@Autowired
private SimpMessagingTemplate messagingTemplate;
@MessageMapping("/getHello")
public void sendReply( MessageHeaders messageHeaders, @Payload String message, @Header(name = "simpSessionId") String sessionId){
messagingTemplate.convertAndSendToUser(sessionId, "/queue/hello", "Hello "+ message, messageHeaders);
}
这个解决方案对我有用。
上下文:您的应用程序没有安全性,您想通过会话 ID 向用户发送消息。 在我们的例子中,另一个词user-id=session-id 。
private final SimpMessageSendingOperations template;
@MessageMapping("/test")
public void testNotification(@Header("simpSessionId") String sessionId, String name) {
String payload = "Hello, " + name + "!";
template.convertAndSendToUser(sessionId, "/ws/notification/message", payload, createHeaders(sessionId));
}
private MessageHeaders createHeaders(String sessionId) {
SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
headerAccessor.setSessionId(sessionId);
headerAccessor.setLeaveMutable(true);
return headerAccessor.getMessageHeaders();
}
以这种方式javascript片段看起来:
stompClient.connect(header, function (frame) {
console.log('Connected: ' + frame);
stompClient.subscribe('/user/ws/notification/message', function (greeting) {
console.log(greeting.body);
});
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.