Я столкнулся с проблемой подключения к WebSocket в моем веб-приложении Spring. Локально, когда я запускаю приложение, соединения WebSocket устанавливаются успешно. Однако после развертывания приложения на сервере в моем домене соединения WebSocket не могут быть установлены. В консоли браузера отображается следующая ошибка:
WebSocket connection to 'wss://merkeido.com/ws/776/1lq4jnfq/websocket' failed:
Дополнительная информация:
Что я пробовал:
Вопрос: Что может привести к сбою соединения WebSocket при развертывании, в частности, к ошибке 403 (запрещено)? Будем очень признательны за любые идеи или предложения по устранению неполадок. Спасибо!
Конфигурация веб-сокета: Вот мой класс конфигурации WebSocket:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/user");
config.setApplicationDestinationPrefixes("/app");
config.setUserDestinationPrefix("/user");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").withSockJS();
}
}
HTML/JavaScript: А вот мой код HTML/JavaScript для установления соединений WebSocket:
<script src = "https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.1.4/sockjs.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
<script th:inline = "javascript">
'use strict';
let stompClient = null;
let selectedUserId = null;
let userId = user_id;
connect();
function connect() {
const socket = new SockJS('/ws');
stompClient = Stomp.over(socket);
stompClient.connect({}, onConnected, onError);
}
function onConnected() {
stompClient.subscribe(`/user/${userId+""}/queue/messages`, onMessageReceived);
stompClient.subscribe(`/user/public`, onMessageReceived);
// Register the connected user
stompClient.send("/app/user.addUser",
{},
JSON.stringify({id: userId+"", c_status: 'ONLINE'})
);
findAndDisplayConnectedUsers().then();
}
</script>
Фактическая ошибка на моей консоли:
Opening Web Socket...
websocket.js:6 WebSocket connection to 'wss://merkeido.com/ws/776/1lq4jnfq/websocket' failed:
e.exports @ websocket.js:6
/ws/776/in3mqa1z/xhr_streaming?t=1714645083452:1
Failed to load resource: the server responded with a status of 403 ()
stomp.min.js:8 Web Socket Opened...
stomp.min.js:8 >>> CONNECT
accept-version:1.1,1.0
heart-beat:10000,10000
Я нашел решение проблемы, внеся несколько изменений в конфигурации WebSocket и WebSecurity.
Конфигурация веб-сокета
Сначала я отредактировал свою конечную точку в классе WebSocketConfig, чтобы обеспечить разрешенные источники:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// Ensure allowed origins
registry.addEndpoint("/ws")
.setAllowedOrigins("https://domain-name.com") // Replace with your client domain
.withSockJS();
}
}
Конфигурация веб-безопасности
Затем я настроил конфигурацию WebSecurity для обработки CORS и CSRF:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/**").permitAll(); // Allow all requests temporarily
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("https://domain-name.com"); // Replace with your client domain
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
Объяснение Конфигурация веб-сокета:
Метод RegisterStompEndpoints регистрирует конечную точку /ws для STOMP через WebSocket и разрешает соединения с https://domain-name.com с использованием SockJS в качестве запасного варианта. Конфигурация веб-безопасности:
Метод configure отключает CSRF и включает CORS, временно разрешая все запросы. Компонент corsFilter настраивает CORS для разрешения учетных данных и запросов от https://domain-name.com, а также всех заголовков и методов. И вот так это работает. Эта настройка гарантирует, что ваше соединение WebSocket и настройки безопасности правильно согласованы, что позволяет вашему клиенту подключаться без проблем.