websockets mvc messagemapping example spring-mvc spring-security spring-boot websocket spring-websocket

spring-mvc - mvc - websocket spring boot angular 4



HabilitaciĆ³n de solicitudes de origen cruzado para WebSockets en Spring (0)

Tengo un servidor OpenShift Wildfly. Estoy construyendo un sitio web con el marco Spring MVC . Una de mis páginas web también usa una conexión WebSocket. En el lado del servidor, he usado la anotación javax.websocket.* y la biblioteca javax.websocket.* Para crear mi 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 proporciona una URL predeterminada, por lo que todas mis páginas web (archivos html) tienen el nombre de host común (canónico). En aras de la simplicidad, estoy llamando a esta URL URL A ( projectname-domainname.rhclound.com ). Creé un alias, CNAME, de la URL A , que se llama URL B (digamos https://www.mywebsite.tech ). URL B es segura, ya que tiene el https .

Estoy usando un cliente JavaScript para conectarme a WebSocket en la ruta /serverendpoint . El URI que estoy usando en mi archivo de página web html, test.html , es el siguiente:

var wsUri = "wss://" + "projectname-domainname.rhclound.com" + ":8443" + "/serverendpoint";

Cuando abro la URL A ( projectname-domainname.rhclound.com/test ), WebSocket se conecta y todo funciona bien. Sin embargo, cuando intento conectarme al websocket usando la URL B ( https://mywebsite.tech/test ), el cliente de JavaScript se conecta y desconecta inmediatamente.

Aquí está el mensaje de la consola que recibo:

Aquí está mi código JavaScript que se conecta a 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 ******/

Después de mucha depuración e intentar varias cosas, llegué a la conclusión de que se trataba de un problema debido al Spring Framework. Esto se debe a que antes de presentar Spring Framework en mi proyecto, la URL B podía conectarse a WebSocket, pero luego de presentar Spring, no puede.
Leí en el sitio web de primavera sobre la política de WebSocket. Me encontré con su misma política de origen que establece que un alias, la URL B , no se puede conectar a WebSocket porque no tiene el mismo origen que la URL A Para resolver este problema, desactivé la misma política de origen con WebSockets como se dice en la documentación, así que agregué el siguiente código. Pensé que al hacerlo arreglaría mi error. Esto es lo que agregué:

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; } }

Sin embargo, esto no solucionó el problema, así que agregué el siguiente método a mi ApplicationConfig que extends WebMvcConfigurerAdapter :

@Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**").allowedOrigins("https://www.mywebsite.com"); }

Esto tampoco funcionó. Entonces probé esto:

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); } }

Esto tampoco funcionó.

Incluso cambié el var wsURI en el código JS a lo siguiente: var wsUri = "wss://" + "www.mywebsite.com" + ":8443" + "/serverendpoint"; Luego var wsUri = "wss://" + "mywebsite.com" + ":8443" + "/serverendpoint";

Cuando hice esto, Google Chrome me dio un error y me dijo que el protocolo de enlace había fallado. Sin embargo, cuando tengo esta URL, var wsUri = "wss://" + "projectname-domianname.rhcloud.com" + ":8443" + "/serverendpoint"; , No obtuve el error de que no se produjo el saludo, pero recibo un mensaje de que la conexión se abrió y se cerró de inmediato (como se vio arriba).

Entonces, ¿cómo puedo solucionar esto?