У меня есть OpenShift Wildfly сервер. Я создаю веб-сайт с помощью рамки Spring MVC
. На одном из моих веб-страниц также используется соединение WebSocket. На стороне сервера я использовал библиотеку @ServerEndpoint
и javax.websocket.*
для создания моего websocket:
package com.myapp.spring.web.controller;
import java.io.IOException;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.springframework.web.socket.server.standard.SpringConfigurator;
@ServerEndpoint(value="/serverendpoint", configurator = SpringConfigurator.class)
public class serverendpoint {
@OnOpen
public void handleOpen () {
System.out.println("JAVA: Client is now connected...");
}
@OnMessage
public String handleMessage (Session session, String message) throws IOException {
if (message.equals("ping")) {
// return "pong"
session.getBasicRemote().sendText("pong");
}
else if (message.equals("close")) {
handleClose();
return null;
}
System.out.println("JAVA: Received from client: "+ message);
MyClass mc = new MyClass(message);
String res = mc.action();
session.getBasicRemote().sendText(res);
return res;
}
@OnClose
public void handleClose() {
System.out.println("JAVA: Client is now disconnected...");
}
@OnError
public void handleError (Throwable t) {
t.printStackTrace();
}
}
OpenShift предоставляет URL по умолчанию, поэтому все мои веб-страницы (html файлы) имеют общее (каноническое) имя хоста. Для простоты я называю этот URL URL A
(projectname-domainname.rhclound.com
). Я создал псевдоним CNAME, URL A
, который называется URL B
(скажем https://www.mywebsite.tech
). URL B
является безопасным, так как он имеет https
.
Я использую клиент JavaScript для подключения к WebSocket по пути /serverendpoint
. URI, который я использую в файле html webpage, test.html
, является следующим:
var wsUri = "wss://" + "projectname-domainname.rhclound.com" + ":8443" + "/serverendpoint";
Когда я открываю URL A
(projectname-domainname.rhclound.com/test
), WebSocket подключается, и все работает нормально. Однако, когда я пытаюсь подключиться к websocket с помощью URL B
( https://mywebsite.tech/test
), клиент JavaScript немедленно подключается и отключается.
Вот сообщение с консоли, которое я получаю:
Вот мой код JavaScript, который подключается к WebSocket:
/****** BEGIN WEBSOCKET ******/
var connectedToWebSocket = false;
var responseMessage = '';
var webSocket = null;
function initWS() {
connectedToWebSocket = false;
var wsUri = "wss://" + "projectname-domainname.rhcloud.com" + ":8443" + "/serverendpoint";
webSocket = new WebSocket(wsUri); // Create a new instance of WebSocket using usUri
webSocket.onopen = function(message) {
processOpen(message);
};
webSocket.onmessage = function(message) {
responseMessage = message.data;
if (responseMessage !== "pong") { // Ping-pong messages to keep a persistent connection between server and client
processResponse(responseMessage);
}
return false;
};
webSocket.onclose = function(message) {
processClose(message);
};
webSocket.onerror = function(message) {
processError(message);
};
console.log("Exiting initWS()");
}
initWS(); //Connect to websocket
function processOpen(message) {
connectedToWebSocket = true;
console.log("JS: Server Connected..."+message);
}
function sendMessage(toServer) { // Send message to server
if (toServer != "close") {
webSocket.send(toServer);
} else {
webSocket.close();
}
}
function processClose(message) {
connectedToWebSocket = false;
console.log("JS: Client disconnected..."+message);
}
function processError(message) {
userInfo("An error occurred. Please contact for assistance", true, true);
}
setInterval(function() {
if (connectedToWebSocket) {
webSocket.send("ping");
}
}, 4000); // Send ping-pong message to server
/****** END WEBSOCKET ******/
После многого отладки и тестирования различных вещей я пришел к выводу, что это проблема, возникающая из-за Spring Framework. Это связано с тем, что до того, как я представил Spring Framework
в моем проекте, URL B
мог подключиться к WebSocket, но после введения Spring он не может.
Я прочитал на spring веб-сайт о политике WebSocket. Я столкнулся с их той же политикой происхождения, которая гласит, что псевдоним URL B
не может подключаться к WebSocket, потому что он не совпадает с тем, t24 > есть. Чтобы решить эту проблему, я отключил одну и ту же политику происхождения с помощью WebSockets, как сказано в документации, поэтому я добавил следующий код. Я думал, что это исправит мою ошибку. Вот что я добавил:
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.socket.AbstractSecurityWebSocketMessageBrokerConfigurer;
@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Override
protected boolean sameOriginDisabled() {
return true;
}
}
Однако это не устранило проблему, поэтому я добавил следующий метод к ApplicationConfig
, который extends WebMvcConfigurerAdapter
:
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("https://www.mywebsite.com");
}
Это тоже не сработало. Затем я попробовал это:
package com.myapp.spring.security.config;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class MyCorsFilter {
// @Bean
// public FilterRegistrationBean corsFilter() {
// System.out.println("Filchain");
// UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
// CorsConfiguration config = new CorsConfiguration();
// config.setAllowCredentials(true);
// config.addAllowedOrigin("https://www.mymt.tech");
// config.addAllowedHeader("*");
// config.addAllowedMethod("*");
// source.registerCorsConfiguration("/**", config);
// FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
// bean.setOrder(0);
// System.out.println("Filchain");
// return bean;
// }
@Bean
public CorsFilter corsFilter() {
System.out.println("Filchain");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); // you USUALLY want this
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
System.out.println("Filchain");
return new CorsFilter(source);
}
}
Это тоже не сработало.
Я даже изменил var wsURI
в JS-коде на следующее:
var wsUri = "wss://" + "www.mywebsite.com" + ":8443" + "/serverendpoint";
Тогда var wsUri = "wss://" + "mywebsite.com" + ":8443" + "/serverendpoint";
Когда я это сделал, Google Chrome дал мне ошибку, заявив, что рукопожатие потерпело неудачу. Однако, когда у меня есть этот URL-адрес, var wsUri = "wss://" + "projectname-domianname.rhcloud.com" + ":8443" + "/serverendpoint";
, я не получил сообщение об ошибке, которое не произошло, но я получил сообщение о том, что соединение открыто и закрыто немедленно (как видно выше).
Итак, как я могу это исправить?