Spring Websockets @SendToUser senza login?
-
02-01-2020 - |
Domanda
Ho una semplice applicazione Spring con funzionalità websocket e finora tutto funziona.Ora voglio inviare un messaggio dal mio server a un client specifico utilizzando l'annotazione @SendToUser.Questo mi dà l'errore "Ignoro messaggio, nessuna informazione principale disponibile".Capisco che non ho alcun accesso sul mio server, quindi ogni utente è "anonimo" e non ha un preside (per ora non sto utilizzando Spring Security).Ma ogni utente ha un ID di sessione.Non è possibile utilizzare l'ID di sessione in qualche modo per distinguere tra gli utenti?Come posso ottenere ciò in modo che i miei utenti ottengano un'entità che corrisponde all'ID sessione?
Soluzione
Penso che una soluzione potrebbe essere quella di evitare l'uso @SendToUser
e usalo crudo SimpMessagingTemplate
e per inviare messaggi a una destinazione che controlli per le sessioni aperte.
Per es.presupponendo che tu abbia un'identità per una nuova sessione websocket, puoi iscriverti a una coda con quell'identificatore nel nome della coda:
stomp.subscribe("/queue/chats" + "-" + mycustomidentifier, onmessage);
Ora, sul lato ascoltatore websocket Spring, puoi indirizzare le tue risposte utilizzando 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());
}
....
Altri suggerimenti
Utilizzare @SendToUser
e aggiungi "/ User /" davanti alla coda durante la sottoscrizione (solo il lato del sottoscrittore).Rest Works Magic: -)
invece di
Java Server: @SendTo("/topic/showResult")
.
e
JS Client: stompClient.subscribe('/topic/showResult', function(calResult){ ....
.
Uso:
Java Server: @SentToUser("/topic/showResult")
e
JS Client: stompClient.subscribe('/user/topic/showResult', function(calResult){ ....
Building on La risposta di Biju e usando il Stomp Generated Session ID (grazie,
Primaveraforework client:
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 Client:
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);
});
});
}
.
Invece dell'ID di Stomp Session è possibile utilizzare il tuo ID sessione del tuo contenitore Web (ad es. JsessionID) ma ora che Cookie è non per impostazione predefinita accessibileDa JavaScript (per Tomcat) Questa è una prospettiva più difficile.
Prova questo.Ha funzionato per me
@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);
}
.