Encabezados de solicitud de origen cruzado (CORS) con encabezados PHP
Tengo un script PHP simple y estoy intentando realizar una solicitud CORS entre dominios:
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: *");
...
Sin embargo, sigo recibiendo el error:
El campo de encabezado de solicitud
X-Requested-With
no está permitido porAccess-Control-Allow-Headers
¿Algo que me falta?
Manejar las solicitudes CORS correctamente es un poco más complicado. Aquí hay una función que responderá de manera más completa (y adecuada).
/**
* An example CORS-compliant method. It will allow any GET, POST, or OPTIONS requests from any
* origin.
*
* In a production environment, you probably want to be more restrictive, but this gives you
* the general idea of what is involved. For the nitty-gritty low-down, read:
*
* - https://developer.mozilla.org/en/HTTP_access_control
* - https://fetch.spec.whatwg.org/#http-cors-protocol
*
*/
function cors() {
// Allow from any origin
if (isset($_SERVER['HTTP_ORIGIN'])) {
// Decide if the origin in $_SERVER['HTTP_ORIGIN'] is one
// you want to allow, and if so:
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400'); // cache for 1 day
}
// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
// may also be using PUT, PATCH, HEAD etc
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
exit(0);
}
echo "You have CORS!";
}
Notas de seguridad
Verifique el encabezado HTTP_ORIGIN con una lista de orígenes aprobados.
Si el origen no se aprueba, entonces debes rechazar la solicitud.
Por favor lea las especificaciones.
TL;DR
Cuando un navegador quiere ejecutar una solicitud entre sitios, primero confirma que está bien con una solicitud "previa" a la URL. Al permitir CORS, le está indicando al navegador que las respuestas de esta URL se pueden compartir con otros dominios.
CORS no protege su servidor. CORS intenta proteger a sus usuarios diciéndoles a los navegadores cuáles deberían ser las restricciones para compartir respuestas con otros dominios. Normalmente, este tipo de intercambio está completamente prohibido, por lo que CORS es una forma de hacer un agujero en la política de seguridad normal del navegador. Estos agujeros deben ser lo más pequeños posible, así que siempre verifique HTTP_ORIGIN con algún tipo de lista interna.
Aquí existen algunos peligros , especialmente si los datos que proporciona la URL normalmente están protegidos. De hecho, está permitiendo que el contenido del navegador que se originó en algún otro servidor lea (y posiblemente manipule) datos en su servidor.
Si va a utilizar CORS, lea atentamente el protocolo (es bastante pequeño) e intente comprender lo que está haciendo. Para ello, en el ejemplo de código se proporciona una URL de referencia.
Seguridad del encabezado
Se ha observado que el encabezado HTTP_ORIGIN es inseguro y eso es cierto. De hecho, todos los encabezados HTTP son inseguros según los distintos significados del término. A menos que un encabezado incluya una firma/hmac verificable, o que toda la conversación esté autenticada a través de TLS, los encabezados son simplemente "algo que el navegador me ha dicho".
En este caso, el navegador dice "un objeto del dominio X quiere obtener una respuesta de esta URL. ¿Está bien?" El objetivo de CORS es poder responder "sí, lo permitiré".
Recibí el mismo error y lo solucioné con el siguiente PHP en mi script de back-end:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
header("Access-Control-Allow-Headers: X-Requested-With");
Access-Control-Allow-Headers
no permite *
como valor aceptado, consulte la documentación de Mozilla aquí .
En lugar del asterisco, debes enviar los encabezados aceptados (primero X-Requested-With
como dice el error).
Actualizar:
*
ahora se acepta es Access-Control-Allow-Headers
.
Según MDN Web Docs 2021 :
El valor
*
solo cuenta como un valor comodín especial para solicitudes sin credenciales (solicitudes sin cookies HTTP o información de autenticación HTTP). En solicitudes con credenciales, se trata como el nombre del encabezado literal*
sin semántica especial. Tenga en cuenta que el encabezado Autorización no puede tener comodines y siempre debe aparecer de forma explícita.