Spring Boot WebSocket STOMP无法发送私信问题排查
Spring Boot 3 WebSocket STOMP 点对点消息无法送达问题
我基于Spring Boot 3实现了一套客户端-服务端聊天应用,采用WebSocket + STOMP协议通信,服务端与客户端使用不同版本的Spring及Spring Boot。目前已实现公共topic消息发送功能,消息经过加密,仅目标客户端可解密查看,但点对点消息始终无法送达目标客户端。
消息处理控制器代码
@Autowired private SimpMessagingTemplate simpMessagingTemplate; @Autowired private ActiveUserStore activeUserStore; @MessageMapping("/send") @SendToUser("/queue/chat") public void sendToUser(@Payload WsIncomingMessage wsIncomingMessage, Principal user, @Header("simpSessionId") String sessionId) { log.info(" /queue/chat > incoming msg: {}, user: {}, header: {}", wsIncomingMessage, user, sessionId); WsOutgoingMessage wsOutgoingMessage = new WsOutgoingMessage(); wsOutgoingMessage.setMessage(wsIncomingMessage.getMessage()); wsOutgoingMessage.setMessageType(wsIncomingMessage.getMessageType()); wsOutgoingMessage.setSentDatetime(wsIncomingMessage.getSentDatetime()); wsOutgoingMessage.setSource(wsIncomingMessage.getSource()); wsOutgoingMessage.setDestination(wsIncomingMessage.getDestination()); wsIncomingMessage.setAdId(wsIncomingMessage.getAdId()); log.info(" /queue/chat > outgoing msg: {}, user: {}, header: {}", wsIncomingMessage, user, sessionId); simpMessagingTemplate.convertAndSendToUser(activeUserStore.getUser(wsOutgoingMessage.getDestination()).getPrincipal(), "/queue/chat", wsOutgoingMessage); }
注:
activeUserStore.getUser(wsOutgoingMessage.getDestination()).getPrincipal()返回用户唯一标识手机号。
自定义握手处理器代码
@Slf4j public class CustomHandshakeHandler extends DefaultHandshakeHandler { @Override protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) { String uuid = UUID.randomUUID().toString(); Principal principal = request.getPrincipal(); if (principal instanceof UsernamePasswordAuthenticationToken) { UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = (UsernamePasswordAuthenticationToken) principal; Object principalObj = usernamePasswordAuthenticationToken.getPrincipal(); if (principalObj instanceof JwtUserDetails) { JwtUserDetails connectingUser = (JwtUserDetails) principalObj; connectingUser.setSessionUuid(uuid); } } log.info("principal in CustomHandshakeHandler: {}", principal); return principal; } }
Principal实例信息
UsernamePasswordAuthenticationToken [Principal=JwtUserDetails(id=3, name=Anupam, principal=+855964572928, password=, sessionUuid=0c4169cd-0289-4233-a6f4-0ec04ea3d08c, authorities=[JwtGrantedAuthority(authorityName=USER)]), Credentials=[PROTECTED], Authenticated=true, Details=null, Granted Authorities=[JwtGrantedAuthority(authorityName=USER)]]
服务端日志信息
消息接收日志
[boundChannel-13][0;39m [36mc.l.c.f.k.c.controller.ChatController [0;39m [2m:[0;39m /queue/chat > incoming msg: WsIncomingMessage(message=Hi, messageType=text/plain, destination=4, sentDatetime=2023-04-29T10:39:49+07:00, source=3, sourceImage=0, adId=no-ad), user: UsernamePasswordAuthenticationToken [Principal=JwtUserDetails(id=3, name=Anupam, principal=+855964572928, password=, sessionUuid=0c4169cd-0289-4233-a6f4-0ec04ea3d08c, authorities=[JwtGrantedAuthority(authorityName=USER)]), Credentials=[PROTECTED], Authenticated=true, Details=null, Granted Authorities=[JwtGrantedAuthority(authorityName=USER)]], header: 36d934da-79d7-f00b-6459-331f1cef60ca [boundChannel-13][0;39m [36mc.l.c.f.k.c.controller.ChatController [0;39m [2m:[0;39m /queue/chat > outgoing msg: WsIncomingMessage(message=Hi, messageType=text/plain, destination=4, sentDatetime=2023-04-29T10:39:49+07:00, source=3, sourceImage=0, adId=no-ad), user: UsernamePasswordAuthenticationToken [Principal=JwtUserDetails(id=3, name=Anupam, principal=+855964572928, password=, sessionUuid=0c4169cd-0289-4233-a6f4-0ec04ea3d08c, authorities=[JwtGrantedAuthority(authorityName=USER)]), Credentials=[PROTECTED], Authenticated=true, Details=null, Granted Authorities=[JwtGrantedAuthority(authorityName=USER)]], header: 36d934da-79d7-f00b-6459-331f1cef60ca
订阅事件日志
event: SessionSubscribeEvent[GenericMessage [payload=byte[0], headers={simpMessageType=SUBSCRIBE, stompCommand=SUBSCRIBE, nativeHeaders={destination=[/user/queue/chat], id=[0]}, simpSessionAttributes={}, simpHeartbeat=[J@197209d9, simpSubscriptionId=0, simpUser=UsernamePasswordAuthenticationToken [Principal=JwtUserDetails(id=3, name=Anupam, principal=+855964572928, password=, sessionUuid=0c4169cd-0289-4233-a6f4-0ec04ea3d08c, authorities=[JwtGrantedAuthority(authorityName=USER)]), Credentials=[PROTECTED], Authenticated=true, Details=null, Granted Authorities=[JwtGrantedAuthority(authorityName=USER)]], simpSessionId=36d934da-79d7-f00b-6459-331f1cef60ca, simpDestination=/user/queue/chat}]]
客户端日志信息
StompSession.Subscription messageSubscriberSubscription = sessionStomp.get().subscribe("/user/queue/chat", messageSubscriber); log.info("messageSubscriberSubscription: {}", messageSubscriberSubscription); 10:39:43.244 [Grizzly(2)] INFO com.lomatechnology.cambodia.fintech.kke.chat.web.ServerCommunication -- messageSubscriberSubscription: Subscription [id=0, destination='/user/queue/chat', receiptId='null', handler=com.lomatechnology.cambodia.fintech.kke.chat.web.MessageSubscriber@39fe1782] 10:39:49.022 [AWT-EventQueue-0] INFO com.lomatechnology.cambodia.fintech.kke.chat.util.DatetimeUtil -- Returned date string: 2023-04-29T10:39:49+07:00 10:39:49.022 [AWT-EventQueue-0] INFO com.lomatechnology.cambodia.fintech.kke.chat.ui.ChatGui -- About to send: WsOutgoingMessage(message=Hi, messageType=text/plain, destination=4, sourceImage=null, sentDatetime=2023-04-29T10:39:49+07:00, source=3, adId=no-ad)
核心疑问
目前服务端能正常接收STOMP消息,客户端订阅也显示成功,但目标客户端始终收不到消息。请问是convertAndSendToUser中Principal的使用有误,还是遗漏了其他配置?
内容的提问来源于stack exchange,提问作者Sandah Aung
相关产品推荐
相关产品推荐

