目前,当成功连接到端点时,我通过响应头将自定义令牌(称为访问令牌)传递回客户端。正确设置了此标头,我可以通过分析HTTP响应来验证标头。
但是,当尝试从帧对象获取标头时,标头未设置(请参阅下面的JavaScript):
stompClient.connect(headers,
function(frame) {
console.log('=========================================');
console.log(frame.headers['access-token']);
console.log(frame);
console.log('=========================================');
stompClient.subscribe('/topic/test', function(stuff){
console.debug(stuff);
});
},
function(error) {
//error code
}
);
我在服务器上设置响应标头如下:
public class HttpSessionHandshakeInterceptorImpl extends HttpSessionHandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
response.getHeaders().set("access-token", token);
return super.beforeHandshake(request, response, wsHandler, attributes);
我删除了一些代码,可以确认是否正在调用拦截器。我认为这不是在调用connect函数时将标头值传递回客户端的正确方法吗?我似乎无法找到有关如何完成此任务的任何文档。感谢。
答案 0 :(得分:0)
ServerHttpResponse响应 - 这是对HTTP请求的响应,您可以更详细地检查(通过记录或在调试模式下)。设置其标头将影响HTTP响应,而不是流经WebSocket连接的STOMP流。 CONNECTED的STOMP标头由消息代理设置。
我不确定,但我怀疑Spring是否能够在STOMP帧中插入额外的标头。 (如果我错了,请纠正我)
答案 1 :(得分:0)
您需要实现ChannelInterceptor并将其注册到输出绑定的通道中
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.util.MultiValueMap;
@Configuration
public class WebSocketServiceCustomHeaderInterceptor implements ChannelInterceptor {
private static final Logger logger = LoggerFactory.getLogger(WebSocketServiceCustomHeaderInterceptor.class);
@Override
@Nullable
public Message<?> preSend(Message<?> message, MessageChannel channel) {
final StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(message);
final StompCommand command = headerAccessor.getCommand();
if (command != null && command == StompCommand.CONNECTED) {
final StompHeaderAccessor accessor = StompHeaderAccessor.create(command);
accessor.setSessionId(headerAccessor.getSessionId());
@SuppressWarnings("unchecked")
final MultiValueMap<String, String> nativeHeaders = (MultiValueMap<String, String>) headerAccessor
.getHeader(StompHeaderAccessor.NATIVE_HEADERS);
accessor.addNativeHeaders(nativeHeaders);
// add custom headers
try {
accessor.addNativeHeader("HOSTNAME", InetAddress.getLocalHost().getHostName());
} catch (UnknownHostException e) {
logger.error("Error getting host name ", e);
}
final Message<?> newMessage = MessageBuilder.createMessage(new byte[0], accessor.getMessageHeaders());
return newMessage;
}
return message;
}
}
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketBrokerConfig implements WebSocketMessageBrokerConfigurer {
@Bean
public WebSocketServiceCustomHeaderInterceptor webSocketServiceCustomHeaderInterceptor() {
return new WebSocketServiceCustomHeaderInterceptor();
}
@Override
public void configureClientOutboundChannel(ChannelRegistration registration) {
registration.interceptors(webSocketServiceCustomHeaderInterceptor());
registration.taskExecutor().corePoolSize(outboundPoolCoreSize).maxPoolSize(outboundPoolMaxSize);
}
}
答案 2 :(得分:0)
恐怕如果没有重大修改,这是不可能的。问题是,在调用ChannelInterceptors之后,标头已完全重建。参见方法def shout(word):
return word.upper()
def introduce():
name = input("What's your name: ")
name = shout(name)
print(f"Hello {name}")
introduce()
StompSubProtocolHandler.convertConnectAcktoStompConnected
方法还将根据消息的类型添加一些标头,例如,调用StompSubProtocolHandler.handleMessageToClient
,如果完成身份验证,则将其设置为标头“用户名”。
我也尝试添加标头,但我要放弃...我的猜测是,在Spring编写STOMP实现的人们都希望严格遵守the specifications