我正在尝试从我的@MessageMapping注解方法中的SimpMessageHeaderAccessor获取主体。
正在使用连接上的ChannelInterceptor设置主体。
即使当我console.log连接帧并看到“user-name”头时,在我的@MessageMapping方法中,Principal始终为空。
感谢您的任何建议:)
消息控制器类:
@Controller
public class MessageController {
private SimpMessagingTemplate template;
public MessageController(SimpMessagingTemplate template) {
this.template = template;
}
@MessageMapping("/private")
public void message(SimpMessageHeaderAccessor accessor, @Payload Message message){
System.out.println(accessor.getUser().getName());
}
}
通道拦截器类别:
@Service
public class CustomHandshakeInterceptor implements ChannelInterceptor {
private JwtUtil jwtUtil;
public CustomHandshakeInterceptor(JwtUtil jwtUtil) {
this.jwtUtil = jwtUtil;
}
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if(StompCommand.CONNECT.equals(accessor.getCommand())){
Object raw = message.getHeaders().get(SimpMessageHeaderAccessor.NATIVE_HEADERS);
if(raw instanceof Map){
Object token = ((Map) raw).get("JWT_TOKEN");
if(token instanceof ArrayList){
System.out.println(((ArrayList<?>) token).get(0).toString());
accessor.setUser(new Principal() {
@Override
public String getName() {
return jwtUtil.extractUsername(((ArrayList<?>) token).get(0).toString());
}
});
}
}
System.out.println("FROM INTERCEPTOR " + accessor.getUser().getName());
}
return message;
}
}
套接字配置类:
@Configuration
@EnableWebSocketMessageBroker
public class SocketConfig implements WebSocketMessageBrokerConfigurer {
private CustomHandshakeInterceptor handshakeInterceptor;
public SocketConfig(CustomHandshakeInterceptor handshakeInterceptor) {
this.handshakeInterceptor = handshakeInterceptor;
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/stomp")
.setAllowedOrigins("http://localhost:3000")
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("queue");
registry.setApplicationDestinationPrefixes("/app");
registry.setUserDestinationPrefix("/users");
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(handshakeInterceptor);
}
}
客户端主控台:
Frame
body: ""
command: "CONNECTED"
headers: {user-name: 'david', heart-beat: '0,0', version: '1.1'}
[[Prototype]]: Object
错误消息:
java.lang.NullPointerException: Cannot invoke "java.security.Principal.getName()" because the return value of "org.springframework.messaging.simp.SimpMessageHeaderAccessor.getUser()" is null
at eu.filip.backend.socket.MessageController.message(MessageController.java:28) ~[classes/:na]
1条答案
按热度按时间cgh8pdjw1#
所以在YouTube和Google上查找之后,我找到了
DefaultHandshakeHandler
类,它有一个返回Principal的determineUser
方法。我基本上自己实现了Principal赋值,并通过SocketConfigregisterStompEndpoints.setHandshakeHandler()
方法添加了它。在这样做之后,我能够在
@MessageMapping
注解方法中检索我的Principal!