Breaking

Post Top Ad

Your Ad Spot

martes, 10 de diciembre de 2019

Como solucionar problemas de CORS

Probablemente ya haya visto errores como el siguiente en la consola de JavaScript de su navegador al intentar ejecutar solicitudes AJAX:
A primera vista, es difícil entender lo que está sucediendo y descubrir de dónde viene el problema. De lo que sí podemos estar seguros es de que los errores están relacionados con el mecanismo CORS (Cross-Origin Resource Sharing). A lo largo de este artículo, describiremos cómo entender lo que está sucediendo y cómo solucionar problemas como estos.

Entendiendo CORS

Con CORS, la aplicación web remota elige si se puede atender la solicitud. La especificación CORS distingue dos casos de uso distintos:
  • Las peticiones sencillas . Este caso de uso se aplica si utilizamos los métodos HTTP GET, HEAD y POST. En el caso de métodos POST, sólo los tipos de contenido con los siguientes valores son compatibles: text/plain.application/x-www-form-urlencodedmultipart/form-data
  • Solicitudes verificadas previamente . Cuando no se aplica el caso de uso de 'solicitudes simples', se realiza una primera solicitud (utilizando el método OPCIONES HTTP) para verificar qué se puede hacer en el contexto de las solicitudes de dominio cruzado.
Los desarrolladores de CORS crearon estos dos escenarios para tener en cuenta los servidores web antiguos que no admiten la especificación. Para obtener más detalles, puede echar un vistazo a esta excelente respuesta en el sitio web de StackOverflow
Tenga en cuenta que si agrega autenticación a la solicitud utilizando el encabezado Autenticación, las solicitudes simples se convierten automáticamente en las comprobadas previamente.
El cliente y el servidor intercambian un conjunto de encabezados para especificar comportamientos con respecto a las solicitudes entre dominios. Echemos un vistazo a ellos ahora. Luego describiremos cómo se usan en ambos casos de uso. Comencemos con encabezados para solicitudes:
  • Origen : el cliente utiliza este encabezado para especificar desde qué dominio se ejecuta la solicitud. El servidor utiliza esta sugerencia para autorizar, o no, la solicitud entre dominios.
  • Método de solicitud de control de acceso : dentro del contexto de solicitudes con verificación previa, la solicitud de OPTIONS envía este encabezado para verificar si el método de destino está permitido en el contexto de solicitudes de dominio cruzado.
  • Acceso-Control-Solicitud-Encabezados : dentro del contexto de solicitudes con verificación previa, la solicitud OPTIONS envía este encabezado para enumerar los encabezados que serán aceptados por el servidor para el método de destino en el contexto de solicitudes de dominio cruzado.
Continuemos con los encabezados para las respuestas:
  • Access-Control-Allow- Credentials : esto especifica si las credenciales son compatibles con las solicitudes entre dominios.
  • Access-Control-Allow-Methods : el servidor usa este encabezado para informar qué métodos están autorizados en el contexto de la solicitud. Esto se usa típicamente en el contexto de solicitudes con verificación previa.
  • Access-Control-Allow-Origin : el servidor usa este encabezado para informar qué dominios están autorizados para la solicitud.
  • Access-Control-Allow-Headers : el servidor usa este encabezado para informar qué encabezados están autorizados en el contexto de la solicitud. Esto se usa típicamente en el contexto de solicitudes con verificación previa.
Enumeramos los encabezados principales de CORS. Se pueden encontrar más detalles sobre el principio CORS en la red de desarrolladores de Mozilla .
Ahora que describimos los fundamentos, veamos estos principios en acción dentro de los navegadores.

Depuración de CORS en el navegador

Para poder averiguar qué está sucediendo, necesitamos aprovechar las herramientas del navegador para ver el mensaje de error y las solicitudes y respuestas intercambiadas. Sin estas sugerencias, es difícil, incluso imposible, comprender el error.
La mayoría de las veces, los desarrolladores trabajan con un cliente REST como Restlet Client  para probar las interacciones con el servicio Web API / REST. En este nivel, las solicitudes funcionan perfectamente dentro del navegador ya que las extensiones de Chrome pueden especificar permisos particulares en su archivo de configuración (manifest.json). El WebRequest uno le permite ejecutar cualquier solicitud en el navegador a través de una extensión. Aquí hay una muestra de configuración:
{ "manifest_version": 2, "short_name": "My Chrome extension", (...) "permissions": [ (...) "webRequest", "webRequestBlocking", "cookies", "<all_urls>", (...) ], (...) }
Las aplicaciones tradicionales del lado del cliente no pueden hacer esto y deben respetar las reglas de CORS cuando ejecutan solicitudes entre dominios. Tenga en cuenta que dichos mecanismos son manejados internamente por el navegador. No hay nada que hacer a nivel de la aplicación ejecutada dentro del navegador.
Para que las cosas funcionen, el mecanismo CORS debe implementarse de la manera correcta, es decir, solicitudes y respuestas con los encabezados correctos. Ahora detallaremos todos estos intercambios.

Solicitudes simples

Como se describió anteriormente, las solicitudes simples se basan en solicitudes únicas, es decir, no hay solicitudes de OPCIONES adicionales. Este caso se refiere a los métodos HTTP GET, HEAD pero también al POST en algunos casos.
Cuando el navegador detecta que la solicitud AJAX no está en el mismo dominio que la página actual, envía automáticamente un encabezado Origin al servidor. Se supone que esto habilita el soporte de CORS en el servidor para la solicitud, y el navegador espera recibir encabezados de CORS en la respuesta. Aquí hay una muestra:
fix-cors-problems_1
Nota: dos solicitudes con el mismo host pero no el mismo puerto no se consideran en el mismo dominio.
Tendremos el mismo comportamiento con una solicitud POST que envía un formulario de carga útil ( tipo de contenido):application/x-www-form-urlencoded
fix-cors-problems_2
Imagine que el servidor no devuelve los encabezados de CORS (por ejemplo, el Access-Control-Allow-Originuno), el navegador mostrará los siguientes errores en la consola de JavaScript:
fix-cors-problems_3
Para depurar el problema, eche un vistazo en la pestaña Red. No podemos encontrar el Access-Control-Allow-Originencabezado en el área "Encabezados de respuesta".
fix-cors-problems_4
El problema no está en la aplicación del cliente sino en la aplicación del servidor. Para solucionarlo, debemos habilitar el soporte de CORS en el nivel del servidor.
Las solicitudes simples son el caso más simple para solicitudes de dominio cruzado. Ahora echemos un vistazo a los verificados previamente.

Solicitudes verificadas previamente

Las solicitudes con verificación previa implican una solicitud de OPCIONES adicional que el navegador ejecuta debajo del capó antes del objetivo. Podemos cambiar al modo de verificación previa muy fácilmente. Por ejemplo:
  • Cambie el tipo de contenido de nuestra solicitud POST anterior de .application/x-www-form-urlencodedapplication/json
  • Use un método HTTP como PUT, PATCH o DELETE
  • Agregue un encabezado HTTP como Autorización para autenticación.
Por esta razón, la diferencia entre solicitudes simples y con verificación previa a menudo puede no estar clara. Esto podría deberse principalmente al soporte del método POST. Por ejemplo, su aplicación puede funcionar para el envío de una carga útil de formulario ( tipo de contenido) pero no con una JSON si el servidor no maneja los métodos OPTIONS correctamente.application/x-www-form-urlencoded
Aquí hay una muestra de una solicitud con verificación previa, con el envío de una carga JSON, utilizando el método POST:
fix-cors-problems_5
Aquí están los detalles de la solicitud de OPCIONES:
fix-cors-problems_6
Es importante tener en cuenta que también podemos tener solicitudes con verificación previa en el caso de un método GET. Ese es el caso si agregamos un Authorizationencabezado a la solicitud GET descrita en la sección anterior.
fix-cors-problems_7
En este contexto, podemos tener varios errores potenciales. Echemos un vistazo a los más comunes y cómo solucionarlos.

Las solicitudes / opciones de CORS no están habilitadas

El primer error es que el servidor no admite los métodos OPTIONS porque no admite CORS en absoluto, o su compatibilidad es mínima y no admite solicitudes con verificación previa. En este caso, veremos un error como este en la consola de JavaScript:
fix-cors-problems_8
Podemos notar que el mensaje menciona la falta de CORS Access-Control-Allow-Originen la respuesta y el código de estado 405 HTTP. Este código de estado es una sugerencia útil para comprender que el servidor no admite solicitudes OPTIONS. Echemos un vistazo a la pestaña Red:
fix-cors-problems_9
Podemos determinar que encontraríamos el mismo problema con un código de estado 4xx. La forma de solucionar este problema consiste en:
  • Agregue el soporte del método OPTIONS para que las solicitudes de verificación previa de CORS sean válidas
  • Agregue el Access-Control-Allow-Originencabezado en su respuesta para que el navegador pueda verificar la validez de la solicitud

Los encabezados de solicitud no son compatibles

Otro error podría ser que los encabezados que queremos usar en nuestra solicitud (por ejemplo, Content-TypeAuthorization) no están habilitados en la respuesta con verificación previa CORS usando el Access-Control-Allow-Headersencabezado. En este caso, tendremos el siguiente error:
fix-cors-problems_10
En la solicitud con verificación previa correspondiente, podemos ver que no Access-Control-Allow-Headersse devuelve ningún encabezado en la respuesta, mientras que la solicitud de destino desea usar el Content-Typeencabezado:
fix-cors-problems_11
Para solucionar este problema, simplemente agregue el encabezado correspondiente en el lado del servidor cuando maneje el método OPTIONS. Luego tendremos las siguientes solicitudes:
fix-cors-problems_12fix-cors-problems_13

Solicitud de OPCIONES no autenticadas

Otro problema común está asociado con el uso del Authorizationencabezado. Lo inusual es que este encabezado no se envía dentro de la solicitud con verificación previa. Por lo tanto, si la aplicación del servidor intenta autenticar todas las solicitudes, incluso las comprobadas previamente, tendremos un error "no autorizado" con el código de estado 401:
fix-cors-problems_14
El servidor debe repararse para que no intente autenticar las solicitudes con verificación previa. Después de haber hecho eso, veríamos las siguientes solicitudes:
fix-cors-problems_15
fix-cors-problems_16

Arreglando problemas

En esta sección, describiremos las posibles soluciones, según el contexto, para solucionar problemas relacionados con CORS.

Actualizando el servidor

La mayoría de las veces, la forma más sencilla de solucionar el problema es actualizar el servidor. La mayoría de las tecnologías del lado del servidor proporcionan soporte para configurar CORS rápidamente. Por ejemplo, con Node y ExpressJS, solo consiste en instalar el middleware CORS y usarlo al inicializar la aplicación Express:
var express = require('express') , cors = require('cors') , app = express(); app.use(cors()); (...)
Hay casos en los que el servicio de destino es de un tercero y la actualización no se puede realizar para admitir CORS. Varios enfoques necesitan ahora ser considerados.

JSONP

El primero es JSONP. Esta técnica se ha utilizado durante mucho tiempo para servicios en línea y solicitudes de dominio cruzado, pero los servicios remotos deben usarla. Consiste en agregar dinámicamente un elemento de script en la página HTML para ejecutar la solicitud. Cuando se recibe la respuesta, el código correspondiente se analiza y ejecuta como JavaScript.
Por esta razón, el contenido de la respuesta debe seguir el siguiente formato:
callbackName([ { name: ‘some value' }, { name: ‘some other value' }])
El nombre de la devolución de llamada se proporciona como un parámetro de la solicitud. La mayoría de las veces y por convención, el nombre del parámetro de devolución de llamada es callbackcAquí hay una solicitud de muestra:
http://somehost/resource/someid?callback=callbackName
Podemos notar que dicho enfoque tiene inconvenientes y restricciones, ya que solo se admiten los métodos GET y la carga útil solo se puede proporcionar como parámetros de consulta.

Proxy de servicio

La última posibilidad restante es agregar un proxy en el lado del servidor dentro de su aplicación, pero requiere un poco de trabajo. Sin embargo, podemos notar que Ionic admite proxy a través de su archivo de configuración ionic.config.json:
(...) "proxies": [{ "path": "/yelp/v3/businesses", "proxyUrl": "https://api.yelp.com/v3/businesses" }] (...)

CORS y API web

Dado que las API web se dirigen a la comunicación entre aplicaciones, la mayoría de las veces admiten CORS de fábrica. Ese es el caso de Restlet Cloud,  nuestra plataforma para implementar y alojar APIs web.
Por ejemplo, para una solicitud de obtener todos los contactos de una tienda utilizando una API web (creada con el asistente de inicio rápido), Cloud gestionará automáticamente la solicitud correspondiente con verificación previa, como se describe a continuación:
fix-cors-problems_17
fix-cors-problems_18
Una característica interesante para mencionar es el soporte de CORS para los archivos, ya que la mayoría de los servidores web estáticos no admiten esta especificación cuando sirven archivos. Restlet Cloud nos permite exponer un almacén de archivos dentro de una API web y tener acceso a su soporte CORS en este contexto.

Conclusión

Como se describe a lo largo del artículo, CORS apunta a solicitudes de dominio cruzado y tiene mecanismos específicos que pueden ser difíciles de depurar. Esto se debe principalmente a las solicitudes con verificación previa que se utilizan en algunos casos y que implican una solicitud de OPCIONES adicional.

No hay comentarios.:

Publicar un comentario

Dejanos tu comentario para seguir mejorando!

Post Top Ad

Your Ad Spot

Páginas