2017-04-04 3 views
0

J'essaye de mettre en application une application simple de Websockets qui peut envoyer des messages d'un point final à une session spécifiée établie ailleurs. Jusqu'à présent, j'ai été en mesure d'utiliser l'annotation @SendToUser() pour qu'un client s'abonne à un canal (comme discuté dans cette question: Spring Websockets @SendToUser without login?)Websockets de ressort sans principal

Cependant, je veux maintenant créer un point d'extrémité distinct qui, lorsque appelé, recherche un utilisateur associé aux données transmises dans ce point de terminaison et envoie un message à cet utilisateur concernant ces données.

Cependant, je n'ai pas été en mesure de déterminer avec précision comment faire pour que je puisse appeler la commande SimPMessagingTemplate convertAndSendToUser() car mes utilisateurs n'ont pas de Principal (je n'utilise pas Spring Security).

J'ai été capable d'obtenir le simpSessionId des MessageHeaders transmis à un point de terminaison @MessageMapping, mais maintenant je ne peux pas comprendre comment utiliser simpSessionId pour envoyer des informations de différentes parties de mon application.

Je l'ai fait des recherches au sujet redéfinissant la méthode de DefaultHandshakeHandler et l'attribution d'un UUID généré au hasard comme le nom d'utilisateur à un utilisateur determineUser() lors de la poignée de main de websocket succès (comme décrit dans une réponse à cette question: How to reply to unauthenticated user in Spring 4 STOMP over WebSocket configuration?), mais depuis le principal à venir est nul Je ne suis pas sûr de savoir comment générer correctement un et l'assigner au Principal pour l'utiliser avec l'application.

J'ai fondamentalement besoin de la possibilité d'avoir des utilisateurs anonymes et de leur envoyer des messages de différentes parties de l'application après qu'ils aient créé une connexion websocket.

Répondre

1

Donc, pour toute personne confrontée à autre un problème similaire, j'ai mis ma propre classe principale:

package hello; 

import java.security.Principal; 
import java.util.Objects; 

public class AnonymousPrincipal implements Principal { 

    private String name; 

    @Override 
    public String getName() { 
     // TODO Auto-generated method stub 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    @Override 
    public boolean equals(Object another) { 
     if (!(another instanceof Principal)) 
      return false; 

     Principal principal = (Principal) another; 
     return principal.getName() == this.name; 

    } 

    @Override 
    public int hashCode() { 
     return Objects.hash(name); 
    } 
} 

Ensuite, je mis en œuvre ma propre version de DefaultHandshakeHandler:

package hello; 

import java.security.Principal; 
import java.util.Map; 
import java.util.UUID; 

import org.springframework.http.server.ServerHttpRequest; 
import org.springframework.web.socket.WebSocketHandler; 
import org.springframework.web.socket.server.support.DefaultHandshakeHandler; 

public class CustomHandshakeHandler extends DefaultHandshakeHandler { 

    @Override 
    protected Principal determineUser(ServerHttpRequest request, 
      WebSocketHandler wsHandler, Map<String, Object> attributes) { 
     Principal principal = request.getPrincipal();   

     if (principal == null) { 
      principal = new AnonymousPrincipal(); 

      String uniqueName = UUID.randomUUID().toString(); 

      ((AnonymousPrincipal) principal).setName(uniqueName); 
     } 

     return principal; 

    } 

} 

maintenant une séance de websocket obtient cette principal attribué lors de la prise de contact si l'utilisateur est anonyme, ils obtiennent un principal anonyme affecté qui me permettra de stocker leur nom (UUID généré) pour une utilisation ultérieure dans d'autres parties de l'application.