Nota: vedere l'aggiornamento in fondo alla domanda per ciò che alla fine ho concluso.Risposta a più volte tramite socket Web senza autenticazione a molla
Ho bisogno di inviare più risposte a una richiesta tramite il socket Web che ha inviato il messaggio di richiesta, il primo rapidamente e gli altri dopo che i dati sono stati verificati (da qualche parte tra 10 e 60 secondi dopo, da più thread paralleli) .
Ho problemi a ottenere le risposte successive per interrompere la trasmissione su tutte le prese web aperte. Come posso far sì che vengano inviati solo alla presa Web iniziale? O dovrei usare qualcosa oltre a Spring STOMP (perché, a dire il vero, tutto quello che voglio è il routing del messaggio a varie funzioni, non ho bisogno o voglio la possibilità di trasmettere ad altre prese, quindi sospetto di poter scrivere il messaggio distributore me stesso, anche se sta reinventando la ruota).
Non sto utilizzando l'autenticazione Spring (questo è stato retrofittato in un codice legacy).
Sul messaggio di ritorno iniziale, posso utilizzare @SendToUser e, anche se non abbiamo un utente, Spring invia solo il valore di ritorno al websocket che ha inviato il messaggio. (vedi this question).
Con le risposte più lente, tuttavia, penso di aver bisogno di usare SimpMessagingTemplate.convertAndSendToUser (utente, destinazione, messaggio), ma non posso, perché devo passare l'utente, e non riesco a capire quale utente è stato utilizzato @SendToUser. Ho provato a seguire i passaggi in this question, ma non è riuscito a farlo funzionare non autenticato (principal.getName() restituisce null in questo caso).
L'ho semplificato notevolmente per il prototipo, quindi non preoccuparti di sincronizzare i thread o altro. Voglio solo che le prese sul web funzionino correttamente.
Ecco il mio controller:
@Controller
public class TestSocketController
{
private SimpMessagingTemplate template;
@Autowired
public TestSocketController(SimpMessagingTemplate template)
{
this.template = template;
}
// This doesn't work because I need to pass something for the first parameter.
// If I just use convertAndSend, it broacasts the response to all browsers
void setResults(String ret)
{
template.convertAndSendToUser("", "/user/topic/testwsresponse", ret);
}
// this only sends "Testing Return" to the browser tab hooked to this websocket
@MessageMapping(value="/testws")
@SendToUser("/topic/testwsresponse")
public String handleTestWS(String msg) throws InterruptedException
{
(new Thread(new Later(this))).start();
return "Testing Return";
}
public class Later implements Runnable
{
TestSocketController Controller;
public Later(TestSocketController controller)
{
Controller = controller;
}
public void run()
{
try
{
java.lang.Thread.sleep(2000);
Controller.setResults("Testing Later Return");
}
catch (Exception e)
{
}
}
}
}
Per la cronaca, qui è il lato del browser:
var client = null;
function sendMessage()
{
client.send('/app/testws', {}, 'Test');
}
// hooked to a button
function test()
{
if (client != null)
{
sendMessage();
return;
}
var socket = new SockJS('/application-name/sendws/');
client = Stomp.over(socket);
client.connect({}, function(frame)
{
client.subscribe('/user/topic/testwsresponse', function(message)
{
alert(message);
});
sendMessage();
});
});
E qui è il config:
@Configuration
@EnableWebSocketMessageBroker
public class TestSocketConfig extends AbstractWebSocketMessageBrokerConfigurer
{
@Override
public void configureMessageBroker(MessageBrokerRegistry config)
{
config.setApplicationDestinationPrefixes("/app");
config.enableSimpleBroker("/queue", "/topic");
config.setUserDestinationPrefix("/user");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry)
{
registry.addEndpoint("/sendws").withSockJS();
}
}
UPDATE: A causa i problemi di sicurezza legati alla possibilità di inviare informazioni su altre web socket rispetto al socket originario , Ho finito col consigliare al mio gruppo che non usiamo l'implementazione Spring 4.0 di STOMP su Web Sockets. Capisco perché il team di Spring ha fatto ciò che hanno fatto, ed è più potere di cui avevamo bisogno, ma le restrizioni di sicurezza sul nostro progetto erano abbastanza severe, e le reali esigenze erano abbastanza semplici, che abbiamo deciso di andare in un modo diverso . Ciò non invalida le risposte di seguito, quindi prendi la tua decisione in base alle esigenze dei tuoi progetti. Almeno abbiamo sperato che tutti abbiano imparato i limiti della tecnologia, nel bene e nel male.
Ho alcuni problemi di sicurezza con questo. Il primo è che qualcuno potrebbe scoprire quale stringa casuale sta usando qualcun altro e ascoltare la conversazione. Il secondo è che qualcuno potrebbe registrarsi per alcune (o tutte, forse) delle potenziali stringhe e ascoltare tutte le risposte. Anche avere fortuna e ascoltare la risposta di un'altra persona non è abbastanza sicuro per questo progetto. Ho davvero bisogno di inviare il messaggio solo su un singolo socket web e sto iniziando a pensare che l'implementazione Spring di STOMP non lo farà .. –
Non dovresti preoccuparti della sicurezza. Basta usare una stringa casuale sufficientemente lunga o usare l'UUID per l'id della sessione. http://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates Fondamentalmente l'hacker avrà bisogno in media di 17 miliardi di anni per rompere il sistema. – medvedev1088
È più probabile che indovinassi la tua password di Gmail che l'hacker indovina l'id della sessione casuale. – medvedev1088