JASoft.org

El blog de José Manuel Alarcón Aguín. Programación web y mucho más...

MENÚ - JASoft: JM Alarcón

JSONP: llamadas AJAX a servidores remotos

Como todo el mundo sabe, una de las medidas de seguridad más acertadas de los navegadores es la del aislamiento de los dominios para proteger la privacidad. Este aislamiento impide que, por defecto, se puedan transferir cookies entre dominios, que fallen los scripts que tratan de afectar a marcos con páginas que están en dominios diferentes y, por supuesto, tampoco permite hacer peticiones desde código JavaScript a servidores que están en dominios diferentes a la actual. Y aún así existen cantidad de vulnerabilidades (Cross Site Scripting, Cross Site Request Forgery, Cross Zone Scripting, etc...) relacionadas con robo de información y ataques distribuidos que están basadas en explotar código de JavaScript en aplicaciones mal construidas. Al final, cómo esté escrito el código de una aplicación web desde el punto de vista de la seguridad es más importante que todos los cortafuegos y otras medidas "de protocolo" que puedas incluir.

Una de las implicaciones de este aislamiento entre dominios es que desde nuestro código JavaScript no podremos llamar a servicios Web que estén ubicados en dominios diferentes al nuestro (con XmlHttpRequest). Esto limita la capacidad de agregar información de diversas aplicaciones para explotarla directamente desde el navegador en nuestros desarrollos. Así que por defecto olvídate de llamar a código de Google, Flicker, eBay, YouTube, etc... y mostrar toda esa información agregada en tu página haciéndolo directamente desde JavaScript.

La solución habitual pasa por construir servicios propios que actúen como intermediarios de otros servicios y nos devuelvan desde nuestro propio servidor la información que necesitemos, lo cual no deja de ser una pesadez.

Una solución alternativa se llama JSONP (JSON with Padding). Fue propuesta en diciembre de 2005 por Bob Ippolito, creador de la biblioteca JavaScript Mochikit, y que desde entonces ha sido adoptada por muchas aplicaciones Web 2.0 como forma de permitir las llamadas a servicios cross-domain.

¿En qué consiste JSONP?

Es una forma de extender la sintaxis de JSON (JavaScript Object Notation, el estándar de facto de intercambio de datos con JavaScript para aplicaciones AJAX) para que soporte llamadas desde otros dominios. Necesita la colaboración del servidor que expone los servicios para generar el código con una determinada sintaxis y se aprovecha de que las etiquetas <script> permiten establecer el origen de scripts externos (atributo SRC) en dominios diferentes al actual, no estando sujetas por tanto a las restricciones impuestas por el aislamiento de dominio.

Pongamos un ejemplo.

Una estructura de datos JSON común podría ser por ejemplo esta:

{ Nombre : "José Manuel" }

La forma normal de procesar estos datos, devueltos por un servicio, por parte de un cliente JavaScript es evaluándolos para crear un objeto JavaScript asignado a una variable y luego hacer uso de ellos.

Si para llamar al servicio escribimos una etiqueta similar a esta (o un método JavaScript que, por debajo, genere algo similar, que es lo habitual):

<script type="text/javascript" language="javascript" src="http://www.otroservidor.com/servicio/dameDatos.asp"/>

indicando en el atributo src la URL del servicio que devuelve los datos, obtendremos sin problema los datos en el cliente. Pero, como JSON define objetos para crear una estructura de datos pero no es directamente código ejecutable, lo que ocurrirá es que el objeto se evaluará pero se descartará inmediatamente.

Este problema se solucionaría si pudiésemos evaluar de algúna manera los datos recibidos desde el servidor remoto. Es aquí donde entra en juego la colaboración de éste. Si definimos en nuestro código JavaScript una función especializada en tratar la información devuelta y conseguimos que el servidor remoto devuelva no sólo los datos "puros" en JSON, sino estos mismos datos envueltos en una llamada a dicha función, el problema estará solucionado.

Esta función puede ser una cuyo nombre esté previamente acordado o bien una que se indique de manera dinámica y que el servidor utilizará como si se tratara de un método de retrollamada o "callback".

Por ejemplo, si tenemos una función llamada "ProcesaDatos" que recibe el objeto JSON y trabaja con él y podemos indicar al servidor remoto que esta es la función en la que nos interesa recibir los datos tendríamos el problema solucionado.

En este ejemplo si pudiésemos escribir esta llamada:

<script type="text/javascript" language="javascript" src=http://www.otroservidor.com/servicio/dameDatos.asp?f=ProcesaDatos/>

para obtener como JavaScript devuelto esto otro:

ProcesaDatos( { Nombre : "José Manuel" } );

lo que tendríamos sería una llamada automática a nuestra función con datos obtenidos desde otro servidor. ¡Justo la llamada entre dominios que estábamos buscando!.

Esta técnica de JSONP tiene muchas aplicaciones y está soportado por la mayor parte de los frameworks de JavaScript que hay por ahí (como jQuery). Pero no está exento de problemas de seguridad. De hecho su existencia es uno de los motivos de que el equipo de ASP.NET incluyera un cambio importante en la forma de devolver los datos JSON en la versión 3.5 del framework quye hace que rompan las aplicaciones AJAX que usan servicios y que fueron creadas con la versión 2.0 de la plataforma.

En un próximo post explicaré esta vulnerabilidad de JSONP en aplicaciones descuidadas, y cuál fue este cambio. En un post posterior tambien me gustaría explicar qué está haciendo el W3C para incluir de manera estándar y segura las llamadas entre dominios y el soporte actual de algunos navegadores.

Mientras tanto quédate con el concepto de JSONP y úsalo con sentido común pues es muy útil en algunas circunstancias.

José Manuel Alarcón
Banner

Agregar comentario