Muchas veces cuando estamos trabajando en nuestros desarrollos Web nos hemos encontrado con alguna situación en la que debemos cargar contenido remoto de forma asincrónica, y este se encuentra un servidor distinto a donde está nuestra aplicación. Por defecto esto no es posible debido a que los navegadores prohiben que las páginas accedan a recursos alojados en servidores externos, esto para evitar que malandros de la programasound y la Internerd hagan de las suyas (?).
Pero, ¿qué pasa si Uds. no son de esos malandros y quieren hacerlo? Hoy les enseñamos como habilitar esto mediante un protocolo llamado CORS, el que permite este tipo de conexiones, tanto a nivel de servidor como de código (en caso de que no tengan acceso a la configuración del servidor).
Toda la información, como siempre, después del salto.
Antes de comenzar, para quienes tienen dudas, una aclaración necesaria:
¿Qué es CORS?
CORS (Cross-Origin-Resource-Sharing) es un mecanismo o protocolo de seguridad que permite hacer peticiones de forma asincrónica a través de Javascript desde un servidor a otro, con el fin de obtener información o recursos para usar en el servidor de origen (que realiza la petición original).
Si bien por defecto los navegadores rechazan este tipo de peticiones, a través de CORS es factible tanto habilitarlas como especificar que tipo de peticiones y desde donde son permitidas.
Con eso claro, vamos al detalle. Específicamente veremos como habilitar CORS de dos formas:
Para habilitar CORS, solo debemos incorporar una línea en el archivo .htaccess del directorio al cual vamos a acceder. En caso de que ese directorio no contenga un .htaccess, podemos crearlo con nuestro editor de texto favorito.
De cualquier forma lo abrimos y agregamos la siguiente línea:
Header add Access-Control-Allow-Origin
"*"
Específicamente lo que estamos haciendo es indicar que ante cualquier petición se agregue una cabecera en la que se indique que se están aceptando peticiones desde distintos servidores al actual, y responder a ellas como si fuesen peticiones locales. El asterisco que aparece al final es un parámetro que representa desde que hosts vamos a aceptar peticiones. En este caso, como indicamos un asterisco, implica que cualquier petición desde cualquier servidor será aceptada y tratada como local, lo que sin duda es un riesgo en términos de seguridad, por lo que se recomienda tratar de restringirlo solo a los servidores que tenemos certeza que las harán, de la siguiente forma:
Header add Access-Control-Allow-Origin
"http://www.example.com"
De esta forma, solo las peticiones que tengan como origen el servidor ‘example.com’ serán aceptadas. Si no tenemos certeza desde donde realizaremos las peticiones, entonces deberemos quedarnos con la original (asterisco).
Para comprobar que las peticiones estén siendo aceptadas, podemos ejecutar CURL a través de consola de la siguiente forma:
curl -I http://www.example.com
Donde example.com es nuestro servidor. El parámetro que va entre curl y el dominio es una i mayúscula. Esto hará que nos retorne solamente las cabeceras del sitio en vez de todo el contenido, y si todo funciona correctamente nos debería mostrar algo como esto:
HTTP/1.1 200 OKDate: Thu, 06 Feb 2014 07:39:02 GMT
Server: Apache/2.2.25
X-Powered-By: PHP/5.3.27
X-Pingback: http://www.example.com/xmlrpc.php
Vary: Accept-Encoding,User-Agent
Access-Control-Allow-Origin: *
Content-Type: text/html; charset=UTF-8
La línea destacada indica que CORS ya está habilitado en el servidor y podemos empezar a hacer peticiones sin problemas.
Nota: Si por alguna razón esto no resulta (no se muestra, o las peticiones aún siguen siendo rechazadas), hay que chequear que tengamos mod_headers habilitados en Apache y/o que no esté desactivada la opción para sobreescribir los archivos .htaccess
Nota 2: Dependiendo de la ubicación del .htaccess (y si no hay otros en niveles inferiores), la misma configuración debería aplicarse a subdirectorios y archivos de ese nivel.
Y ahora, ¿qué pasa si no tenemos acceso a editar los archivos .htaccess?. Para eso está nuestra segunda opción, habilitar las cabeceras a nivel de código.
Esto es aún más sencillo que lo anterior. Para habilitar CORS, solo debemos ir al archivo PHP sobre el cual realizaremos una petición e incluir lo siguiente:
if (isset($_SERVER['HTTP_ORIGIN'])) { header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}"); header('Access-Control-Allow-Credentials: true'); header('Access-Control-Max-Age: 86400'); } if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS"); if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); }
El código anterior genera un efecto similar a lo que vimos en el número 1. Cuando el script en PHP se ejecute, automáticamente se añadirán las cabeceras que permiten el acceso remoto (mediante la función header que pasa como parámetro el tipo de cabecera a insertar). Adicionalmente podemos agregar cabeceras para las opciones y/o tipos de peticiones que se aceptarán (en la sección OPTIONS del código anterior). Esto último es opcional.
Guardamos y hacemos la prueba, con lo que deberíamos poder realizar la petición sin problemas.
Y con eso podemos habilitar CORS, tanto a través de servidor como a nivel de código.
Antes de terminar, les recordamos que como siempre este tutorial ha sido desarrollado, probado y documentado por el equipo de Cómo Lo Hago, por lo que cuenta con nuestro sello de garantía:
Cualquier duda o comentarios que puedan tener, los invitamos a dejarnos unas líneas a continuación.
Esperamos que este tutorial haya sido de utilidad para Uds.
¡Hasta la próxima!
6:45:07 am
Muy buenos tutoriales los que poneis sencillos y practicos
7:56:16 am
[…] Muchas veces cuando estamos trabajando en nuestros desarrollos Web nos hemos encontrado con alguna situación en la que debemos cargar contenido remoto de forma asincrónica, y este se encuentra un servidor distinto … […]
6:57:17 am
Buenos dias.
Estoy atascado en un proyecto IOT ( Internet of Thinks) y te expongo mi caso esperando por favor que me eches un cable.
Tengo un server montado en un dispositivo ESP8266, el cual responde a las peticiones enviadas desde mi navegador. Por ejemplo si en la barra de direcciones escribo :
” http://192.168.43.174/?pin=datos” , recibo una respuesta del dispositivo en forma de web.
Como la petición viene de un dominio distinto recibo el mensaje de error que hace referencia a : Access-Control-Allow-Origin
He leido que hay que poner en la respuesta del server una cabecera que diga :
Access-Control-Allow-Origin * …..para que el navegador no me suelte un error pero no se exactamente como formar la cabecera.
Supongo que debe ser algo como : o algo asi pero no lo acierto.
¿Puedes ayudarme?
Gracias, un saludo.
1:02:45 pm
Hola, mencionan como solucionarlo con php, pero si lo estoy haciendo con java, cómo lo solucionaría?
Gracias
6:18:31 pm
amigo mi problema es que yo uso son sub-dominios en mi dominio y cuando hago una llamada o un cambio me aparece ese error…. en donde colocaria la linea “Access-Control-Allow-Origin * ” en que .htaccess???? ya lo coloque por codigo php y no funciono….
1:55:24 pm
Every weekend i used to pay a visit this web page, for the reason that i wish for
enjoyment, for the reason that this this web site conations really good funny material too.
8:18:03 pm
I am actually delighted to glance at this weblog posts which carries
lots of valuable facts, thanks for providing these information.
12:28:34 am
I visit each day a few blogs and websites to read articles,
except this webpage offers quality based content.
12:50:22 am
Pretty nice post. I just stumbled upon your weblog and wanted to mention that I’ve really loved browsing your blog posts.
After all I will be subscribing to your feed and
I am hoping you write once more very soon!
12:56:56 am
Really when someone doesn’t understand then its up to other people that they will
assist, so here it takes place.