Spring WebSockets: Send beskeder til en bestemt bruger

1. Introduktion

I denne vejledning beskriver vi, hvordan du gør det Brug Spring WebSockets til at sende STOMP-meddelelser til en enkelt bruger. Det er vigtigt, fordi vi undertiden ikke vil sende alle meddelelser til hver bruger. Derudover demonstrerer vi, hvordan du sender disse meddelelser på en sikker måde.

For en introduktion til WebSockets, se denne fantastiske vejledning for, hvordan du kommer i gang. Og for at få et dybere dykke ind i sikkerheden skal du tjekke denne artikel for at sikre din implementering af WebSockets.

2. Køer, emner og slutpunkter

Der er tre vigtigste måder at sige, hvor beskeder sendes, og hvordan de abonnerer på ved hjælp af Spring WebSockets og STOMP:

  1. Emner - almindelige samtaler eller chatemner åbne for enhver klient eller bruger
  2. Køer - forbeholdt specifikke brugere og deres aktuelle sessioner
  3. Slutpunkter - generiske slutpunkter

Lad os nu se hurtigt på et eksempel på en kontekststi for hver:

  • “/ Emne / film”
  • “/ Bruger / kø / specifik bruger”
  • “/ Sikret / chat”

Det er vigtigt at bemærke det vi skal bruge køer til at sende meddelelser til bestemte brugere, da emner og slutpunkter ikke understøtter denne funktionalitet.

3. Konfiguration

Lad os nu lære at konfigurere vores applikation, så vi kan sende meddelelser til en bestemt bruger:

offentlig klasse SocketBrokerConfig udvider AbstractWebSocketMessageBrokerConfigurer {@Override public void configureMessageBroker (MessageBrokerRegistry config) {config.enableSimpleBroker ("/ secure / user / queue / specific-user"); config.setApplicationDestinationPrefixes ("/ spring-security-mvc-socket"); config.setUserDestinationPrefix ("/ sikret / bruger"); } @ Override public void registerStompEndpoints (StompEndpointRegistry registry) {registry.addEndpoint ("/ secure / room"). WithSockJS (); }}

Lad os sørge for at inkludere en brugerdestination, da det bestemmer, hvilke slutpunkter der er reserveret til enkeltbrugere.

Vi har også forud for alle vores køer og brugerdestinationer med “/ Sikret” for at få dem til at kræve godkendelse. For ubeskyttede slutpunkter kan vi droppe “/ Sikret” præfikset (som et resultat af vores andre sikkerhedsindstillinger).

Fra en pom.xml standpunkt, er der ikke behov for yderligere afhængigheder.

4. URL-tilknytninger

Vi ønsker, at vores klient abonnerer på en kø ved hjælp af en URL-kortlægning, der overholder følgende mønster:

"/ bruger / kø / opdateringer"

Denne kortlægning transformeres automatisk af UserDestinationMessageHandler ind i den brugersessionsspecifikke adresse.

For eksempel, hvis vi har en bruger, der hedder “Bruger123”, ville den tilsvarende adresse være:

"/ kø / opdateringer-bruger123"

På serversiden sender vi vores brugerspecifikke svar ved hjælp af følgende URL-kortlægningsmønster:

"/ bruger / {brugernavn} / kø / opdateringer"

Også dette vil blive omdannet til den korrekte URL-kortlægning, som vi allerede abonnerede på klientsiden.

Således ser vi det de væsentlige ingredienser her er dobbelt:

  1. Prepend vores specificerede destination for brugerdestination (konfigureret i AbstractWebSocketMessageBrokerConfigurer).
  2. Brug "/kø" et eller andet sted inden for kortlægningen.

I det næste afsnit ser vi nøjagtigt på, hvordan man gør dette.

5. Påkald convertAndSendToUser ()

Vi kan ikke statisk påberåbe os convertAndSendToUser () fra SimpMessagingTemplate eller SimpMessageSendingOperations:

@Autowired privat SimpMessagingTemplate simpMessagingTemplate; @MessageMapping ("/ secure / room") public void sendSpecific (@Payload Message msg, Principal user, @Header ("simpSessionId") String sessionId) kaster Exception {OutputMessage out = new OutputMessage (msg.getFrom (), msg.getText (), nyt SimpleDateFormat ("HH: mm"). format (ny dato ())); simpMessagingTemplate.convertAndSendToUser (msg.getTo (), "/ secure / user / queue / specific-user", out); }

Du har måske bemærket:

@Header ("simpSessionId") Streng sessionId

Det @Header annotation giver adgang til overskrifter, der er eksponeret af den indgående meddelelse. For eksempel kan vi få fat i strømmen Sessions ID uden behov for komplicerede interceptors. Tilsvarende vi kan få adgang til den aktuelle bruger via Rektor.

Det er vigtigt, at den tilgang, vi tager i denne artikel, giver større tilpasning i forhold til @sendToUser kommentar med hensyn til URL-tilknytninger. For mere om denne kommentar, tjek denne fantastiske artikel.

Kundesiden bruger vi Opret forbindelse() i JavaScript til initialisere en SockJS-forekomst og oprette forbindelse til vores WebSocket-server ved hjælp af STOMP:

var-sokkel = ny SockJS ('/ sikret / rum'); var stompClient = Stomp.over (stikkontakt); var sessionId = ""; stompClient.connect ({}, funktion (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 (" Din nuværende session er: "+ url); sessionId = url;} 

Vi har også adgang til det leverede Sessions ID og tilføj det til " sikret / værelse URL-kortlægning. Dette giver os muligheden for dynamisk og manuelt at levere en brugerspecifik abonnementskø:

stompClient.subscribe ('sikret / bruger / kø / specifik bruger' + '-bruger' + that.sessionId, funktion (msgOut) {// håndter meddelelser} 

Når alt er sat op, skal vi se:

Og i vores serverkonsol:

6. Konklusion

Se den officielle forårsblog og den officielle dokumentation for at få flere oplysninger om dette emne.

Som altid er kodeeksemplerne, der bruges i denne artikel, tilgængelige på GitHub.