Spring WebSockets: stuur berichten naar een specifieke gebruiker

1. Inleiding

In deze zelfstudie beschrijven we hoe u dit kunt doen gebruik Spring WebSockets om STOMP-berichten naar een enkele gebruiker te sturen. Dat is belangrijk omdat we soms niet elk bericht naar elke gebruiker willen uitzenden. Daarnaast laten we zien hoe u deze berichten op een veilige manier kunt versturen.

Bekijk deze geweldige tutorial voor een inleiding tot WebSockets om aan de slag te gaan. En, voor een diepere duik in beveiliging, bekijk dit artikel om uw WebSockets-implementatie te beveiligen.

2. Wachtrijen, onderwerpen en eindpunten

Er zijn drie belangrijke manieren om te zeggen waar berichten naartoe worden gestuurd en hoe ze zijn geabonneerd met Spring WebSockets en STOMP:

  1. Onderwerpen - veelvoorkomende gesprekken of chatonderwerpen die openstaan ​​voor elke klant of gebruiker
  2. Wachtrijen - gereserveerd voor specifieke gebruikers en hun huidige sessies
  3. Eindpunten - generieke eindpunten

Laten we nu voor elk snel een voorbeeld van een contextpad bekijken:

  • "/ Topic / movies"
  • "/ Gebruiker / wachtrij / specifieke gebruiker"
  • "/ Beveiligd / chat"

Het is belangrijk om dat op te merken we moeten wachtrijen gebruiken om berichten naar specifieke gebruikers te sturen, aangezien onderwerpen en eindpunten deze functionaliteit niet ondersteunen.

3. Configuratie

Laten we nu leren hoe we onze applicatie kunnen configureren zodat we berichten naar een specifieke gebruiker kunnen sturen:

openbare klasse SocketBrokerConfig breidt AbstractWebSocketMessageBrokerConfigurer uit {@Override public void configureMessageBroker (MessageBrokerRegistry-configuratie) {config.enableSimpleBroker ("/ secure / user / queue / specific-user"); config.setApplicationDestinationPrefixes ("/ spring-security-mvc-socket"); config.setUserDestinationPrefix ("/ beveiligd / gebruiker"); } @Override public void registerStompEndpoints (StompEndpointRegistry-register) {registry.addEndpoint ("/ secure / room"). WithSockJS (); }}

Laten we ervoor zorgen dat u een gebruikersbestemming opneemt, aangezien die bepaalt welke eindpunten zijn gereserveerd voor afzonderlijke gebruikers.

We voegen ook een voorvoegsel aan al onze wachtrijen en gebruikersbestemmingen toe "/beveiligd" om ervoor te zorgen dat ze authenticatie vereisen. Voor onbeschermde eindpunten kunnen we het "/beveiligd" prefix (als gevolg van onze andere beveiligingsinstellingen).

Van een pom.xml standpunt, zijn er geen aanvullende afhankelijkheden vereist.

4. URL-toewijzingen

We willen dat onze klant zich abonneert op een wachtrij met behulp van een URL-toewijzing die voldoet aan het volgende patroon:

"/ gebruiker / wachtrij / updates"

Deze mapping wordt automatisch getransformeerd door UserDestinationMessageHandler in het gebruikerssessie-specifieke adres.

Als we bijvoorbeeld een gebruiker hebben met de naam "User123", zou het bijbehorende adres zijn:

"/ wachtrij / updates-user123"

Server-side sturen we ons gebruikersspecifieke antwoord met behulp van het volgende URL-toewijzingspatroon:

"/ gebruiker / {gebruikersnaam} / wachtrij / updates"

Ook dit zal worden omgezet in de juiste URL-toewijzing die we al aan de clientzijde hebben geabonneerd.

Dus we zien dat de essentiële ingrediënten zijn hier tweeledig:

  1. Voeg onze opgegeven gebruikersbestemmingsvoorvoegsel (geconfigureerd in AbstractWebSocketMessageBrokerConfigurer).
  2. Gebruik "/wachtrij" ergens binnen de mapping.

In de volgende sectie zullen we bekijken hoe u dit precies moet doen.

5. Inroepen convertAndSendToUser ()

We kunnen niet-statisch een beroep doen op convertAndSendToUser () van SimpMessagingTemplate of SimpMessageSendingOperations:

@Autowired privé SimpMessagingTemplate simpMessagingTemplate; @MessageMapping ("/ secure / room") public void sendSpecific (@Payload Message msg, hoofdgebruiker, @Header ("simpSessionId") String sessionId) genereert uitzondering {OutputMessage out = new OutputMessage (msg.getFrom (), msg.getText (), nieuwe SimpleDateFormat ("UU: mm"). format (nieuwe datum ())); simpMessagingTemplate.convertAndSendToUser (msg.getTo (), "/ beveiligd / gebruiker / wachtrij / specifieke gebruiker", uit); }

Het is je misschien opgevallen:

@Header ("simpSessionId") String sessionId

De @Koptekst annotatie geeft toegang tot kopteksten die worden weergegeven door het inkomende bericht. We kunnen bijvoorbeeld de stroom pakken sessionId zonder de noodzaak van ingewikkelde interceptors. Evenzo we hebben toegang tot de huidige gebruiker via Opdrachtgever.

Belangrijk is dat de aanpak die we in dit artikel volgen, meer maatwerk biedt dan de @sendToUser annotatie met betrekking tot URL-toewijzingen. Bekijk dit geweldige artikel voor meer informatie over die annotatie.

Client-side, we zullen gebruiken aansluiten() in JavaScript naar initialiseer een SockJS-instantie en maak verbinding met onze WebSocket-server met STOMP:

var socket = nieuwe SockJS ('/ secure / room'); var stompClient = Stomp.over (socket); var sessionId = ""; stompClient.connect ({}, functie (frame) {var url = stompClient.ws._transport.url; url = url.replace ("ws: // localhost: 8080 / spring-security-mvc-socket / secure / room / "," "); url = url.replace (" / websocket "," "); url = url.replace (/ ^ [0-9] + \ //," "); console.log (" Uw huidige sessie is: "+ url); sessionId = url;} 

We hebben ook toegang tot de meegeleverde sessionId en voeg dat toe aan de " beveiligd / kamer URL-toewijzing. Dit geeft ons de mogelijkheid om dynamisch en handmatig een gebruikerspecifieke wachtrij voor abonnementen op te geven:

stompClient.subscribe ('secure / user / queue / specific-user' + '-user' + that.sessionId, function (msgOut) {// berichten afhandelen} 

Zodra alles is ingesteld, zouden we moeten zien:

En in onze serverconsole:

6. Conclusie

Bekijk de officiële Spring-blog en de officiële documentatie voor meer informatie over dit onderwerp.

Zoals altijd zijn de codevoorbeelden die in dit artikel worden gebruikt, beschikbaar op GitHub.


$config[zx-auto] not found$config[zx-overlay] not found