Búsqueda de sitios web

javascript - La solicitud tiene éxito en el servidor pero resulta en un error CORS en el navegador


Hago una solicitud HTTP POST al inicio de sesión de Microsoft para obtener un token de acceso para usar con la API de correo, la solicitud tiene éxito pero el código va a la cláusula de error de mi código.

requestAccessToken(code: string)
{
console.log("request access token");
if (code) {
  var headers = new Headers();
  headers.append("Content-Type", 'application/x-www-form-urlencoded');
  headers.append('Accept', 'application/json');
  var requestoptions = new RequestOptions({
    headers: headers
  });
  var body = `grant_type=authorization_code&
              redirect_uri=http://localhost:4200&
              code=`+ code + `&
              client_id=4e[................]5ab&
              client_secret=CE[..............]BC`;

  this.http.post("https://login.microsoftonline.com/common/oauth2/v2.0/token", body, requestoptions).map((res: Response) =>
  {
    console.log("response given");
    const data = res.json();
  }).subscribe( (data) => {
     console.log("The data is = " + data); 
  }, error => { 
    console.log("The error is = " + error)
  });
}

La consola del navegador muestra esto: XMLHttpRequest no puede cargar https://login.microsoftonline.com/common/oauth2/v2.0/token. No hay un encabezado 'Access-Control-Allow-Origin' presente en el recurso solicitado. Por lo tanto, no se permite el acceso al origen 'http://localhost:4200'. zone.js:2019 XHR falló al cargar: POST "https://login.microsoftonline.com/common/oauth2/v2.0/token". outlook.service.ts:96 El error es=Respuesta con estado: 0 para URL: null

aquí hay una captura de pantalla para mostrarlo mejor

Ahora el verdadero problema es que mi solicitud tiene éxito como se muestra a continuación:

y la respuesta muestra mi token de acceso. Entonces, ¿por qué no puedo obtenerlo desde el código? ¿Por qué va a la cláusula de error?

Respuesta #1

Lo que estás viendo es un comportamiento esperado al enviar una solicitud de origen cruzado a un servidor pero no recibir el encabezado de respuesta Access-Control-Allow-Origin en la respuesta.

Específicamente, mientras tu solicitud de origen cruzado no tenga características que hagan que tu navegador realice una solicitud OPTIONS de preflight antes de hacer tu solicitud, la solicitud tendrá éxito en el lado del servidor, pero, debido a que la respuesta del servidor a esa solicitud no incluye el encabezado de respuesta Access-Control-Allow-Origin, tu navegador bloquea que tu código frontend pueda realmente ver la respuesta que envía el servidor.

Sin embargo, si abres las herramientas de desarrollo del navegador, aún puedes ver la respuesta allí. Pero solo porque el navegador haya recibido la respuesta y puedas verla en las herramientas de desarrollo, no significa que el navegador exponga la respuesta a tu código. Solo la expondrá cuando tenga Access-Control-Allow-Origin.

Todo eso puede parecer contraintuitivo, pero todo tiene sentido si recuerdas que el navegador es el único punto en el que se aplican las restricciones de origen cruzado. Los servidores no bloquean las solicitudes de origen cruzado.

Cuando el servidor al que envías esa solicitud recibe la solicitud, no verifica el origen para decidir si responder. El servidor simplemente acepta la solicitud y la procesa y luego envía una respuesta. Pero luego el navegador bloquea el acceso de tu código a esa respuesta.

Pero también es importante recordar que el navegador no bloquea tu código de enviar esa solicitud entre orígenes. Los navegadores solo bloquean que se envíen solicitudes entre orígenes cuando las solicitudes tienen características (como encabezados especiales) que hacen que el navegador realice un preflight.

Entonces, si tu solicitud no es una que active una verificación previa (preflight), el navegador la envía y el servidor la recibe y la procesa. Y si el método de la solicitud es POST u otro cuyo propósito es cambiar el estado en el servidor —en cuyo caso puede que no te importe mucho cuál sea la respuesta— entonces, en la medida en que la solicitud haya tenido el efecto previsto en el lado del servidor, puede considerarse exitosa.

Pero considera lo que sucede cuando realmente te importa mucho cuál es la respuesta: considera lo que sucede con las solicitudes GET, donde todo el propósito de hacer la solicitud es recibir una respuesta.

Como se explicó arriba, si la solicitud no es una que desencadene un preflight, el navegador la envía, el servidor la recibe y devuelve una respuesta. Pero si la respuesta no incluye el encabezado de respuesta Access-Control-Allow-Origin, tu navegador no permitirá que tu código JavaScript del frontend la acceda.

Obviamente, dado que todo el objetivo de hacer una solicitud GET es hacer algo con la respuesta, entonces en ese caso, si tu código no puede acceder a la respuesta, eso es un fallo completo y total — en contraste con el caso de la solicitud POST, donde el cuerpo de la solicitud sí se envía como se esperaba, pero simplemente no tienes una manera para que tu código verifique la respuesta para ver si la solicitud fue exitosa.

Artículos relacionados