La política de mismo origen es un mecanismo de seguridad implementado por los navegadores que impide que scripts de diferentes orígenes lean o modifiquen recursos de otros dominios sin autorización explícita. Por ejemplo, un script ubicado en a.com no puede utilizar ajax para obtener datos de b.com debido a esta restricción.
Se considera que dos URLs tienen el mismo origen cuando comparten idénticamente el protocolo (http/https), el nombre de dominio y el número de puerto.
Elementos no afectados por esta política:
- Los enlaces, redirecciones y envíos de formularios pueden ejecutarse sin restricciones entre dominios distintos.
- La carga de recursos desde otros dominios está permitida, aunque JavaScript no puede acceder al contenido de dichos recursos. Esto aplica para etiquetas como <script src="...">, <img>, <link> e <iframe>.
La técnica JSONP aprovecha precisamente esta excepción: el atributo src de la etiqueta script no está sujeto a las restricciones de cross-origin, por lo que permite recuperar datos de otros dominios.
Funcionamiento de JSONP:
(Ejemplo: página en a.com/consulta.html necesita obtener datos del archivo b.com/servicio.php) Desde a.com/consulta.html se define una función de callback denominada datosRecibidos, se crea dinámicamente un elemento <script> y se configura su atributo src hacia el servidor remoto, incluyendo un parámetro calblack con el nombre de la función. La petición queda construida así: http://b.com/main.js?callback=datosRecibidos. El servidor en jsonp.php invoca la función datosRecibidos pasándole los datos en formato JSON como argumento.
Ejemplo práctico: URL de destino: http://www.ejemplo.com/api/datos?callback=procesarInformacionDatos JSON esperados: ["usuario1","usuario2"] Respuesta real enviada al navegador: procesarInformacion(["usuario1","usuario2"])
<?php
header('Content-type: application/json');
//Recuperar el nombre de la función callback
$nombreCallback = filter_input(INPUT_GET, 'cb', FILTER_SANITIZE_STRING);
//Datos JSON a enviar
$informacion = '["usuario1","usuario2"]';
//Devolver datos en formato JSONP
echo $nombreCallback . "(" . $informacion . ")";
?>
//Página del cliente
//<div id="contenedorResultados"></div>
<script type="text/javascript">
function procesarInformacion(respuesta, nombreMetodo)
{
var salida = ''; for(var i = 0; i < respuesta.length; i++) { salida += '- ' + respuesta\[i\] + '
'; } salida += '';
document.getElementById('contenedorResultados').innerHTML = salida;
}
</script>
<script type="text/javascript" src="http://www.ejemplo.com/api/datos?cb=procesarInformacion"></script>
Implementar JSONP presenta limitaciones importantes:
- Cualquier sitio web puede solicitar y obtener los datos del servidor remoto, lo cual representa un riesgo de seguridad considerable. Es necesario establecer mecanismos de autenticación mediante tokens entre las partes involucradas.
- Únicamente soporta el método GET, no es posible utilizar POST para el envío de información.
- El servidor puede devolver código malicioso que se ejecutará en el navegador, modificando el contenido de la página. Se recomienda implementar sanitización de cadenas para mitigar este problema.