Error "Ignoring message, no principal info available" when using websocket in spring

StackOverflow https://stackoverflow.com/questions/23487620

  •  16-07-2023
  •  | 
  •  

Question

In my system, I use custom login mechanism, so tomcat and spring do not know authenticated user info. When I subscribe endpoint:

stompClient.subscribe("/user/queue/position-updates", function(message) {...});

spring will complaint "Ignoring message, no principal info available". I traced into the code, and find spring will try to get principle info from session in DefaultUserDestinationResolver class, but none will be gotten, so the error message is given.

My questions are: Does spring websocket depend on security mechanism of tomcat or spring? Can I set the authenticated user info to principle of http session manually?

Thanks!

Was it helpful?

Solution

The user in the WebSocketSession comes from the HttpServletRequest.getUserPrincipal() when the session starts (i.e. the handshake request). You can either wrap the HTTP request (e.g. from a filter) and override the method returning the user, or you can also extend DefaultHandshakeHandler (see the determineUser protected method). Both the Java and XML config provide a way to configure a custom HandshakeHandler.

OTHER TIPS

You can implement HandshakeHandler like this.

public class HandshakeHandler extends DefaultHandshakeHandler {
Logger logger = (Logger) LoggerFactory.getLogger(HandshakeHandler.class);
@Override
protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) {
    Principal principal = request.getPrincipal();

    if(principal==null)
    {
        ServletServerHttpRequest req= (ServletServerHttpRequest)request;
        HttpSession session = req.getServletRequest().getSession();
        final User user = (User) session.getAttribute("user");
        principal=new Principal() {
            @Override
            public String getName() {
                return user!=null?user.getId():"";
            }
        };
    }
    logger.debug("principal:{}",principal);
    return principal;
}

}

And then declare it in your xml.

<bean id="handshakeHandler" class="x.x.x.HandshakeHandler"/>

<websocket:message-broker application-destination-prefix="/app">
  <websocket:stomp-endpoint path="/ws">
      <websocket:handshake-handler ref="handshakeHandler"/>
      <websocket:sockjs/>
  </websocket:stomp-endpoint>
  <websocket:simple-broker prefix="/topic, /queue"/>
</websocket:message-broker>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top