Encabezados de solicitud de origen cruzado (CORS) con encabezados PHP

146

Tengo un script PHP simple que estoy intentando 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-Withno está permitido porAccess-Control-Allow-Headers

¿Algo que me falta?

Machavity
fuente

Respuestas:

59

Access-Control-Allow-Headersno permite *como valor aceptado, consulte la documentación de Mozilla aquí .

En lugar del asterisco, debe enviar los encabezados aceptados (primero X-Requested-Withcomo dice el error).

KARASZI István
fuente
289

Manejar las solicitudes CORS correctamente es un poco más complicado. Aquí hay una función que responderá más completamente (y correctamente).

/**
 *  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
 *  - http://www.w3.org/TR/cors/
 *
 */
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!";
}
arma cortante
fuente
32
Tenga en cuenta que devolver el valor de Origen HTTP como el origen permitido permitirá que cualquier persona le envíe solicitudes con cookies, lo que podría robar una sesión de un usuario que inició sesión en su sitio y luego vio la página de un atacante. Desea enviar '*' (que no permitirá las cookies y evitará el robo de sesiones) o los dominios específicos para los que desea que funcione el sitio.
Jules
1
Convenido. En la práctica, probablemente no permitiría que cualquier dominio antiguo use su servicio CORS, lo restringiría a un conjunto en el que decidió confiar.
slashingweapon
Para su información, esta solución sólo trabajó para mí en una Linux server, en IISpor alguna razón no funcionó, no sé si es mi alojamiento o simplemente que no es adecuado paraIIS
ncubica
1
¡Gracias! Tengo que marcar esta respuesta. Lástima que no podamos marcar esto como una nueva respuesta
Ascherer
1
¡Lo único que realmente funciona! .. Solo cambie Access-Control-Allow-Origin: * TO Access-Control-Allow-Origin: {$ _SERVER ['HTTP_ORIGIN']}
Renan Franca
60

Obtuve el mismo error y lo arreglé 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");
Fiach Reid
fuente
35

Muchas descripciones en Internet no mencionan que especificar Access-Control-Allow-Originno es suficiente. Aquí hay un ejemplo completo que me funciona:

<?php
    if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Methods: POST, GET, DELETE, PUT, PATCH, OPTIONS');
        header('Access-Control-Allow-Headers: token, Content-Type');
        header('Access-Control-Max-Age: 1728000');
        header('Content-Length: 0');
        header('Content-Type: text/plain');
        die();
    }

    header('Access-Control-Allow-Origin: *');
    header('Content-Type: application/json');

    $ret = [
        'result' => 'OK',
    ];
    print json_encode($ret);
Csongor Halmai
fuente
1
Explique por qué no es suficiente y qué ejemplo mínimo es suficiente.
halfpastfour.am
Desafortunadamente, no recuerdo exactamente y ahora no tengo tiempo para investigarlo nuevamente, pero, por lo que recuerdo, hubo algunas suposiciones básicas del lado del servidor web / navegador que hicieron que no funcionara. Este fue el código mínimo que funcionó para mí.
Csongor Halmai
24

Simplemente he logrado que dropzone y otros complementos funcionen con esta solución (angularjs + backend php)

 header('Access-Control-Allow-Origin: *'); 
    header("Access-Control-Allow-Credentials: true");
    header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
    header('Access-Control-Max-Age: 1000');
    header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');

agregue esto en upload.php o donde enviaría su solicitud (por ejemplo, si tiene upload.html y necesita adjuntar los archivos a upload.php, luego copie y pegue estas 4 líneas). Además, si está utilizando complementos / complementos CORS en Chrome / Mozilla, asegúrese de alternarlos más de una vez, para que CORS esté habilitado

Fedeco
fuente
15

Si desea crear un servicio CORS desde PHP, puede usar este código como el primer paso en su archivo que maneja las solicitudes:

// Allow from any origin
if(isset($_SERVER["HTTP_ORIGIN"]))
{
    // You can decide if the origin in $_SERVER['HTTP_ORIGIN'] is something you want to allow, or as we do here, just allow all
    header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
}
else
{
    //No HTTP_ORIGIN set, so we allow any. You can disallow if needed here
    header("Access-Control-Allow-Origin: *");
}

header("Access-Control-Allow-Credentials: true");
header("Access-Control-Max-Age: 600");    // cache for 10 minutes

if($_SERVER["REQUEST_METHOD"] == "OPTIONS")
{
    if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"]))
        header("Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT"); //Make sure you remove those you do not want to support

    if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"]))
        header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");

    //Just exit with 200 OK with the above headers for OPTIONS method
    exit(0);
}
//From here, handle the request as it is ok
Finn Johansen
fuente
8

CORS puede convertirse en un dolor de cabeza, si no entendemos correctamente su funcionamiento. Los uso en PHP y funcionan sin problemas. referencia aquí

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Max-Age: 1000");
header("Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Cache-Control, Pragma, Authorization, Accept, Accept-Encoding");
header("Access-Control-Allow-Methods: PUT, POST, GET, OPTIONS, DELETE");
sombras3002
fuente
7

Este código me funciona cuando utilizo angular 4 como el lado del cliente y PHP como el lado del servidor.

header("Access-Control-Allow-Origin: *");
Labib Hussain
fuente
3

Esto debería funcionar

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Cache-Control, Pragma, Authorization, Accept, Accept-Encoding");
usuario8453321
fuente
0

agregue este código en .htaccess

agregue claves de autenticación personalizadas en el encabezado como app_key, auth_key..etc

Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers: "customKey1,customKey2, headers, Origin, X-Requested-With, Content-Type, Accept, Authorization"
Rakyesh Kadadas
fuente
-1

En Windows, pegue este comando en la ventana de ejecución solo por un momento para probar el código

chrome.exe --user-data-dir = "C: / sesión de desarrollo de Chrome" --disable-web-security

Fazil Raza
fuente
Desactivar la seguridad web de su navegador, incluso temporalmente, es una idea terrible
Machavity