Cross domain
No es la primera vez que me he tenido que enfrentar al problema del “Cross Domain” y aunque es relativamente sencillo de solucionar, he descubierto una nueva forma de resolverlo.
Pero antes, para el que no lo conozca, definiremos el Cross Domain.
Básicamente, es la necesidad de carga de información desde otro dominio. Por ejemplo, si desde nuestro dominio http://quepuedohacer.es se necesita cargar información de otro dominio, imaginemos que queremos sacar el tiempo que hace en nuestra ciudad utilizando el dominio www.aemet.es, y para ello utilizamos un navegador WEB moderno, se producirá el error de “Cross Domain”.
El problema es originado por la seguridad que los navegadores intentan aplicar en nuestra navegación. Entre otros existen 2 formas habituales de sabotaje en internet y que consiguen evitar los navegadores:
- El “Cross Site Request Forgery” o XSRF, que consiste en que al navegar por páginas WEB maliciosas (entiende esto como páginas ya desarrolladas con este código malicioso o que han sido hackeadas), intentan suplantar al usuario mediante peticiones a WEBs. Date cuenta que en la mayoría de las WEB en las que nos tenemos que identificar (por ejemplo, en tu banco habitual) solemos (aunque no deberíamos) recordar nuestra contraseña, y peor aún hacer que nuestro navegador nos recuerde. Esto se suele hacer con cookies. Si al acceder a una página de estas que nos dejan ver películas piratas ;), correríamos el riesgo de que el HTML de esta página lanzara una petición a nuestro banco y que pudiera operar de forma transparente para nosotros. Imagínate lo caro que nos saldría esa película.
- El otro mecanismo es el denominado “Cross Site Scripting” o XSS. En este caso la WEB maliciosa no nos suplanta, pero nos roba información gracias. Esto se hace mediante la inyección de código (habitualmente JS) en comentarios, formularios, etc.
La cuestión es que, en nuestro beneficio, los navegadores modernos NO permiten que una página WEB pueda solicitar información a otros dominios que no sean nuestros.
En el caso de intentar cargar información entre dominios nos aparecerá un error similar a este:
Solicitud desde otro origen bloqueada.
¿Cómo puedo probar el error? Sencillo.
- Abre un navegador WEB y arranca una página. El buscador de Google puede servir.
- Ahora pulsa F12, lo que debería abrirte en la parte inferior el cuadro de herramientas.
- Ahora busca la pestaña de consola y escribe el siguiente código. (en mi caso lo haré con el Mozilla Firefox).
var i = new XMLHttpRequest();
i.open('GET', 'http://www.aemet.es/xml/municipios/localidad_28079.xml', true);
i.send();
Y ejecuta el código. (Suele funcionar con CTRL+Enter).
OK, nuestro navegador nos mantiene seguros, pero ¿Qué ocurre con nuestro ejemplo en el que simplemente queremos mostrar información del tiempo de nuestra ciudad llamando a un XML de ese dominio ajeno a nosotros?
Existen varias formas para resolver este problema, aunque solo la primera resuelve 100% el problema.
Proxy
Este método consiste en que realmente mi HTML NO llama a ese dominio al que no puedo acceder, sino que llama a una página dentro de mi propio dominio que simplemente hace una llamada al dominio inalcanzable y devuelve su resultado.
Para hacer esto podemos utilizar cURL o mejor aún aplicar una regla a nuestro servidor WEB para que actúe como proxy. Por ejemplo, aplicando la siguiente regla en .htaccess.
RewriteRule “^/tiempo/(.*)$” “http://www.aemet.es/xml/municipios/localidad_$1.xml” [P]
La regla anterior convertirá (en nuestro servidor WEB) la petición http://midominio/tiempo/28079 a http://www.aemet.es/xml/municipios/localidad_28079.xml.
Pero claro, muchos estaréis pensando que de esta forma deberíamos definir reglas para cada uno de los dominios a los que queramos acceder. Pues sí. Para evitar esto podéis utilizar soluciones como cURL, que permite hacer llamadas a URL desde nuestro servidor y devolver su resultado, pero mediante un código programado. OJO, deberemos evitar definir páginas del tipo http://midominio/proxy?url=http://www.aemet.es/xml/municipios/localidad_28079.xml.
¿Por qué el cuidado anterior? Bueno, tenemos que pensar que un atacante podría utilizar esa página para llamar a direcciones ajenas y perpetrar un ciberataque desde nuestro servidor WEB. (Hace poco, concretamente el 21 de octubre del 2016, Twiter y otras redes sociales sufrierón un ataque de denegación de servicio seguramente debido a equipos y servidores zombie) ¿Cómo solucionamos esto? La solución debería ser la de bloquear a que portales deberemos dejar acceder nuestro servidor mediante la utilización del proxy.
Peticiones Script
Esta solución consiste en la posibilidad de crear Scripts en nuestro HTML que permite la llamada a código externo. Pensad que, cuando llamamos al Script de Google Analytics o al de JQuery, estamos haciendo peticiones a otros dominios.
El problema es que también estamos protegidos ante la descarga de fichero que no sean puramente código JavaScript. Pero claro, ¿Quién nos dice que una petición no se haga a una página que devuelva un inofensivo “vas a;”, pero que haya realizado alguna operación? Por ejemplo, un registro de información…
El caso es que el erro que recibiríamos es “Cargando contenido visual mixto (no seguro)” o “Se ha bloqueado la carga del contenido activo mixto”.
Un ejemplo de esto sería con el siguiente código.
var s=document.createElement("SCRIPT");
s.src="http://www.aemet.es/xml/municipios/localidad_28079.xml";
s.defer="defer";
document.head.appendChild(s);
Como podéis imaginar, la única solución para esto es la llamada a recursos que devuelvan datos en como script, por ejemplo, llamadas a Servicios WEB (SW) o Servicios REST que devuelvan en formato JSONP.
CORS
El Intercambio de Recursos de Origen Cruzado (CORS, Cross-Origen Resource Sharing), es un mecanismo que permite compartir nuestros ficheros hacia terceros.
Este mecanismo, que ya tiene sus añitos (es del 2014), es el que me ha motivado a escribir este POST.
¿Quién tiene que aplicar CORS?
Se tendrán que configurar todos los Dominios o Aplicaciones WEB que pretendan ofrecer sus recursos de forma compartida para posibles reutilizadores.
En nuestro caso lo tendría que aplicar AEMET, bien para su dominio completo o solo para las URL que devuelven los XML.
¿En qué consiste CORS?
Básicamente CORS consiste en un protocolo en el que el recurso accesible (el XML, JSON, etc.), permite el acceso a través de peticiones asíncronas a otros dominios en un navegador WEB.
El navegador negocia con el domino al que queremos acceder para obtener la información y confirmando en él.
¿Es esto seguro?
Tal y como lo tienen planteado, debería serlo. Daros cuenta que, por ejemplo, nuestro banco NO debería permitir el acceso a otros dominios, pero AEMET SÍ debería dejar acceder a un XML que por otro lado están dando de forma pública.
Por otro lado, no todas las peticiones están permitidas. En la WEB de referencia de Mozilla, tenéis una información más detallada sobre lo que está permitido y lo que no está permitido.
Aun así, si nos la quieren liar, lo podrán seguir haciendo.
Recuerda que puedes dejar tus comentarios sobre si te ha gustado el POST, si no le has visto utilidad, si quieres que lo amplíe más, haga un vídeo con los ejemplos, etc.
Un saludo.