informatica:programacion:cursos:programacion_avanzada_javascript:ajax
Diferencias
Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anteriorRevisión previaPróxima revisión | Revisión previa | ||
| informatica:programacion:cursos:programacion_avanzada_javascript:ajax [2024/10/14 11:27] – [DEMO: Una base de datos de películas con JSONP] tempwin | informatica:programacion:cursos:programacion_avanzada_javascript:ajax [2024/10/30 15:46] (actual) – [Funcionamiento básico de CORS] tempwin | ||
|---|---|---|---|
| Línea 20: | Línea 20: | ||
| La tendencia actual en todos los desarrollos web, sin embargo, es crear **aplicaciones y páginas cada vez más parecidas a aplicaciones de escritorio**, | La tendencia actual en todos los desarrollos web, sin embargo, es crear **aplicaciones y páginas cada vez más parecidas a aplicaciones de escritorio**, | ||
| - | <WRAP center round todo 60%> | + | {{ : |
| - | AJAX | + | |
| - | </ | + | |
| Ya hemos aprendido a lo largo de este curso las posibilidades que ofrecen los navegadores actuales para trabajar en el lado cliente con HTML, CSS y JavaScript. La tendencia imparable en las aplicaciones web es la de **llevar cada vez más procesamiento y lógica al navegador**, | Ya hemos aprendido a lo largo de este curso las posibilidades que ofrecen los navegadores actuales para trabajar en el lado cliente con HTML, CSS y JavaScript. La tendencia imparable en las aplicaciones web es la de **llevar cada vez más procesamiento y lógica al navegador**, | ||
| Línea 653: | Línea 651: | ||
| </ | </ | ||
| </ | </ | ||
| + | |||
| + | Scripts usados: | ||
| + | |||
| + | * '' | ||
| + | * '' | ||
| El contenido de '' | El contenido de '' | ||
| Línea 661: | Línea 664: | ||
| function hacerBusqueda() { | function hacerBusqueda() { | ||
| - | var titPelicula = document.getElementById(" | + | |
| - | if (titPelicula.trim() == "" | + | if (titPelicula.trim() == "" |
| - | alert(" | + | alert(" |
| - | document.getElementById(" | + | document.getElementById(" |
| - | } | + | } |
| - | sendJsonpRequest(IMDB_API_URL + "? | + | |
| } | } | ||
| function titPelicula_OnEnter(event) { | function titPelicula_OnEnter(event) { | ||
| - | event = EventHandlerHelper.fixEvent(event); | + | |
| - | if (event.which == 13) | + | if (event.which == 13) |
| - | hacerBusqueda(); | + | hacerBusqueda(); |
| } | } | ||
| //Muestra resultados de búsqueda (función callback de JSONP) | //Muestra resultados de búsqueda (función callback de JSONP) | ||
| function mostrarResultadosBusquedaCallback(resultados) { | function mostrarResultadosBusquedaCallback(resultados) { | ||
| - | var resHTML = ""; | + | |
| - | + | ||
| - | if (!resultados.Search || resultados.Search.length == 0){ | + | if (!resultados.Search || resultados.Search.length == 0){ |
| - | resHTML = "< | + | resHTML = "< |
| - | } | + | } |
| - | else { | + | else { |
| - | for(var i = 0; i< | + | for(var i = 0; i< |
| - | { | + | { |
| - | var res = resultados.Search[i]; | + | var res = resultados.Search[i]; |
| - | resHTML += "<p data-imdbid='" | + | resHTML += "<p data-imdbid='" |
| - | } | + | } |
| - | } | + | } |
| - | document.getElementById(" | + | document.getElementById(" |
| - | ocultarDetalles(); | + | ocultarDetalles(); |
| } | } | ||
| Línea 697: | Línea 700: | ||
| function error404() | function error404() | ||
| { | { | ||
| - | document.getElementById(" | + | |
| - | ocultarDetalles(); | + | ocultarDetalles(); |
| } | } | ||
| Línea 704: | Línea 707: | ||
| //Se le pasa el elemento sobre el que se ha pulsado | //Se le pasa el elemento sobre el que se ha pulsado | ||
| function mostrarInfoPeli(elto) { | function mostrarInfoPeli(elto) { | ||
| - | var idPelicula = elto.attributes[" | + | |
| - | //Desmarco las que hubiese seleccionadas | + | //Desmarco las que hubiese seleccionadas |
| - | var seleccionados = document.getElementsByClassName(" | + | var seleccionados = document.getElementsByClassName(" |
| - | for(var i = 0; i< seleccionados.length; | + | for(var i = 0; i< seleccionados.length; |
| - | seleccionados[i].className = ""; | + | seleccionados[i].className = ""; |
| - | } | + | } |
| - | //La marco como seleccionada | + | //La marco como seleccionada |
| - | elto.className = " | + | elto.className = " |
| - | //Pido la info sobre la película | + | //Pido la info sobre la película |
| - | sendJsonpRequest(IMDB_API_URL + "? | + | sendJsonpRequest(IMDB_API_URL + "? |
| } | } | ||
| //Muetra información de una película (función callback de JSONP) | //Muetra información de una película (función callback de JSONP) | ||
| function mostrarInfoPeliculaCallback(peli){ | function mostrarInfoPeliculaCallback(peli){ | ||
| - | if (peli != null && !peli.Error) | + | |
| - | { | + | { |
| - | //Asignamos a mano la imagen | + | //Asignamos a mano la imagen |
| - | if (peli.Poster == " | + | if (peli.Poster == " |
| - | document.getElementById(" | + | document.getElementById(" |
| - | else { | + | else { |
| - | document.getElementById(" | + | document.getElementById(" |
| - | document.getElementById(" | + | document.getElementById(" |
| - | } | + | } |
| - | //Ahora asignamos el resto de los campos | + | //Ahora asignamos el resto de los campos |
| - | enlazarCamposConDOM(peli); | + | enlazarCamposConDOM(peli); |
| - | mostrarDetalles(); | + | mostrarDetalles(); |
| - | } | + | } |
| } | } | ||
| //Se encarga de localizar campos en la página con el mismo nombre que campos de un objeto que se le pasa, e introduce su valor como contenido en cada uno de ellos | //Se encarga de localizar campos en la página con el mismo nombre que campos de un objeto que se le pasa, e introduce su valor como contenido en cada uno de ellos | ||
| function enlazarCamposConDOM(obj) { | function enlazarCamposConDOM(obj) { | ||
| - | //Si no se pasa un elemento concreto del DOM a partir del cual buscar, se usa document y se busca en toda la página | + | |
| //Se recorren las propiedades del objeto | //Se recorren las propiedades del objeto | ||
| - | for (prop in obj) { | + | |
| - | // | + | // |
| - | var e = document.getElementById(prop); | + | var e = document.getElementById(prop); |
| - | if (e != null) { | + | if (e != null) { |
| - | e.textContent = obj[prop]; | + | e.textContent = obj[prop]; |
| - | } | + | } |
| } | } | ||
| Línea 749: | Línea 752: | ||
| //Mostrar detalles película | //Mostrar detalles película | ||
| function mostrarDetalles(){ | function mostrarDetalles(){ | ||
| - | document.getElementById(" | + | |
| } | } | ||
| //Ocultar detalles película | //Ocultar detalles película | ||
| function ocultarDetalles(){ | function ocultarDetalles(){ | ||
| - | document.getElementById(" | + | |
| } | } | ||
| function initialize() { | function initialize() { | ||
| - | EventHandlerHelper.addEventListener(document.getElementById(" | + | |
| - | EventHandlerHelper.addEventListener(document.getElementById(" | + | EventHandlerHelper.addEventListener(document.getElementById(" |
| } | } | ||
| Línea 765: | Línea 768: | ||
| </ | </ | ||
| - | ===== ===== | + | <WRAP center round tip 60%> |
| + | Visor online para JSON: https:// | ||
| + | </ | ||
| ===== Control de acceso entre dominios: CORS ===== | ===== Control de acceso entre dominios: CORS ===== | ||
| + | |||
| + | La funcionalidad de JSONP que acabamos de estudiar es muy interesante para crear //mashups// y manejar información de otros dominios de manera directa desde el navegador. Sin embargo, hay que tener cuidado cuando se usa con información privada importante ya que **no está exenta de problemas de seguridad**. Por algo los que diseñan los navegadores se empeñan en no permitir el acceso entre dominios. | ||
| + | |||
| + | <WRAP center round info 60%> | ||
| + | **Mashups**: | ||
| + | </ | ||
| + | |||
| + | No voy a entrar en detalles aquí sobre técnicas de //phising// que usan JavaScript para obtener ilícitamente información de otros dominios mediante JSONP, pero baste decir que Twitter o el mismísimo GMail fueron craqueados hace años usando técnicas de [[https:// | ||
| + | |||
| + | El protegerse de esas técnicas de //hacking// depende del servicio que implementa la API JSONP. Sólo deberíamos usarlo en nuestras páginas si confiamos en estos sitios. Utilizar APIs de servicios poco recomendables podría resultar en problemas de seguridad para nuestros usuarios. | ||
| + | |||
| + | Además JSONP tiene bastantes limitaciones: | ||
| + | |||
| + | * Sólo sirve para peticiones GET | ||
| + | * Los datos deben devolverse en formato JSON, o sea, JavaScript. Si necesitamos otros formatos no lo tenemos fácil. | ||
| + | * La información que se puede enviar al servidor es muy limitada (únicamente datos planos como parámetros de la URL). | ||
| + | * El servidor debe colaborar explícitamente con el método para devolver el código envuelto en una llamada a un método JavaScript, algo que no siempre está en nuestra mano. | ||
| + | * No existe un método estándar para controlar el acceso a este tipo de recursos remotos por parte del servidor que los provee, es decir, decidir quién y cuándo puede acceder al recurso. | ||
| + | |||
| + | Así que, realmente, **la mejor manera de crear aplicaciones AJAX sigue siendo usar el objeto '' | ||
| + | |||
| + | Conscientes de ello el W3C trabajó en un **estándar que modifica el modo de funcionamiento tradicional** del objeto '' | ||
| + | |||
| + | Los principales navegadores lo han implementado hace bastante tiempo (Internet Explorer desde la versión 8, Opera desde la 12). Si te interesa puedes leer el estándar completo aquí: [[http:// | ||
| + | |||
| + | <WRAP center round important 60%> | ||
| + | Nota: Muchos programadores cuando oyen hablar de CORS piensan en un protocolo de seguridad para proteger el acceso a los recursos, de manera similar a tener una clave o usar un mecanismo de cifrado o algo similar. Se trata de **un error de concepto**. CORS no pretende proteger el acceso a las aplicaciones de servidor. No es un método de seguridad para servicios en Internet. Lo que busca es **proteger a los usuarios frente a ataques de phishing y XSRF** para que no sean víctimas de un pirata de forma inadvertida, | ||
| + | </ | ||
| + | |||
| + | ==== Funcionamiento básico de CORS ==== | ||
| + | |||
| + | CORS define un protocolo entre los servidores Web y los navegadores para que colaboren a la hora de delimitar políticas de seguridad de acceso entre dominios. | ||
| + | |||
| + | Así, en su forma más básica, CORS define que cuando se haga una llamada con XHR a un dominio diferente del actual, **dicha llamada debe incluir automáticamente información sobre quién realiza la petición**. Así ésta incluirá automáticamente una cabecera llamada " | ||
| + | |||
| + | <WRAP center round info 60%> | ||
| + | Nota: Esta cabecera difiere de la cabecera " | ||
| + | </ | ||
| + | |||
| + | Con esta cabecera el servidor decide si permite o no el acceso al recurso, devolviendo en su respuesta una cabecera de tipo " | ||
| + | |||
| + | Por ejemplo, puede devolver: | ||
| + | |||
| + | < | ||
| + | Access-Control-Allow-Origin: | ||
| + | </ | ||
| + | |||
| + | Al recibir esta cabecera el navegador sabe si debe permitir o no que se realice la llamada. De esta forma se protege a los usuarios, ya que si alguien intenta un ataque XSRF contra un servicio como GMail, al realizar la petición desde otro dominio distinto al esperado ('' | ||
| + | |||
| + | Por defecto, si el servidor no incluye esta cabecera el navegador bloquea la llamada, con lo que el comportamiento es exactamente el mismo que el tradicional. | ||
| + | |||
| + | En muchos casos, si el servicio quiere que pueda consumirse desde cualquier dominio, puede devolver esto: | ||
| + | |||
| + | < | ||
| + | Access-Control-Allow-Origin: | ||
| + | </ | ||
| + | |||
| + | Esto significa que admite peticiones desde cualquier dominio externo. Ideal para servicios que no juegan con datos privados y quieren abrirse a cuantos más usuarios externos mejor. | ||
| + | |||
| + | La especificación CORS define todavía más cabeceras para cuestiones algo más especializadas, | ||
| + | |||
| + | Lo mejor de CORS es que nosotros, como programadores JavaScript no tenemos que hacer nada especial para soportar estas llamadas entre dominios. Nos limitamos a utilizar el objeto XHR como siempre, de la manera explicada en este tema. La única diferencia es que tenemos que incluir el URL completo, con el nombre de otro dominio. | ||
| + | |||
| + | A la hora de utilizar un servicio externo desde uno de tus desarrollos JavaScript, intenta averiguar si el servicio implementa cabeceras CORS de tipo " | ||
| + | ===== Recursos ===== | ||
| + | |||
| + | * [[https:// | ||
informatica/programacion/cursos/programacion_avanzada_javascript/ajax.1728898076.txt.gz · Última modificación: por tempwin
