【发布时间】:2021-02-22 04:46:12
【问题描述】:
我正在尝试在使用 Java spring 和 Angular 8 构建的现有 Jhipster 应用程序中连接到 websocket。在创建项目时,我没有选择 websocket 选项,现在需要实现项目中的 websockets。我从“https://www.jhipster.tech/using-websockets/”获得帮助并尝试实施相同的解决方案,但我收到握手失败消息。 我在 websockets 中使用 STOMP 和 sockJS。 请让我知道握手失败的原因。
这里是 websocket configuration.java 文件。
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
import hr.nic.vc.security.AuthoritiesConstants;
import java.security.Principal;
import org.springframework.http.server.*;
import java.util.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.*;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.*;
import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
@Configuration
@EnableWebSocketMessageBroker
public class WebsocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config)
{
config.enableSimpleBroker("/topic");
//config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry
registry) {
registry.addEndpoint("/websocket/blog").setHandshakeHandler(defaultHandshakeHandler())
.setAllowedOrigins("*").withSockJS();
}
@Bean
public HandshakeInterceptor httpSessionHandshakeInterceptor() {
return new HandshakeInterceptor() {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
attributes.put(IP_ADDRESS, servletRequest.getRemoteAddress());
}
return true;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
}
};
}
private DefaultHandshakeHandler defaultHandshakeHandler() {
return new DefaultHandshakeHandler() {
@Override
protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) {
Principal principal = request.getPrincipal();
if (principal == null) {
Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority(AuthoritiesConstants.ANONYMOUS));
principal = new AnonymousAuthenticationToken("WebsocketConfiguration", "anonymous", authorities);
}
return principal;
}
};
}
}
这是 websocket 安全文件。
public class WebsocketSecurityConfiguration extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages)
{
messages.nullDestMatcher().authenticated().simpDestMatchers("/topic/blog")
.authenticated()
// matches any destination that starts with /topic/
// (i.e. cannot send messages directly to /topic/)
// (i.e. can’t subscribe to /topic/messages/* to get messages which is sent to
// /topic/messages-user)
.simpDestMatchers("/topic/**").authenticated();
// message types other than MESSAGE and SUBSCRIBE
//.simpTypeMatchers(SimpMessageType.MESSAGE, SimpMessageType.SUBSCRIBE).denyAll()
// catch all
//.anyMessage().denyAll();
}
/**
* Disables CSRF for Websockets.
*/
@Override
protected boolean sameOriginDisabled() {
return true;
}
}
这里是连接websocket认证后调用的connect方法。
connect():void {
console.log("connect called"); //eslint-disable-line
// build absolute path, websocket doesn't fail during deploying with a context path
let url = '/websocket/blog';
url = this.location.prepareExternalUrl(url);
const authToken = this.authServerProvider.getToken();
if (authToken) {
url += '?access_token=' + authToken;
}
const socket = new SockJS(url);
this.stompClient = Stomp.over(socket);
const headers = {};
this.stompClient.connect(headers, () => {
console.log("this is inside stompclient connect connect"); //eslint-disable-line
this.stompClient.subscribe('/topic/blog', data => {
console.log("This inside subscription"); //eslint-disable-line
this.listenerObserver.next(JSON.parse(data.body));
});
});
}
}
授权令牌以正确的值传递。因此授权没有错误。 请让我知道是否需要其他任何内容。 我在这一点上卡了很长时间。
错误:
WebSocket connection to 'ws://localhost:8080/websocket/blog/587/mklduqvp/websocket?access_token=eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJoYXJkZWVwc2h1a2xhMDhAbmljLmluIiwiYXV0aCI6IlJPTEVfRU1QTE9ZRUUiLCJleHAiOjE2MDUyNDUwNjd9.DJ2HITaVAiaphd2yg3yPAiLrLI4n8MjszjBasC3zOHrC-73mFdltDPEYHihY16VzPv0rh6EYLj84zCBv37TDNA' failed: Error during WebSocket handshake: Unexpected response code: 200
【问题讨论】:
-
您是否尝试过生成与旧项目相同设置的新项目并复制配置?
-
是的,我试过了。仍然没有运气。与上述相同的错误。
-
新生成的项目工作正常。我试图将 websocket 配置添加到现有项目中。我也更新了错误。请看一下
-
新旧项目的Jhipster版本相同。是的,我检查了服务器端日志,没有错误,只有客户端显示此错误。我没有在调试器中运行服务器,因为这两个项目完全不同。
-
调试器将向您显示消息代理中的执行,这不是您的代码,因此两个项目之间是相同的,只是它的初始化应该不同并触发不同的行为。对于
org.springframework.web.socket,服务器日志可能不在 DEBUG 级别,因此您看不到comapre 发生了什么。
标签: spring-boot websocket jhipster stomp sockjs