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

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

  •  16-07-2023
  •  | 
  •  

質問

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!

役に立ちましたか?

解決

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.

他のヒント

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>
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top