Cabeçalhos de solicitação de origem cruzada (CORS) com cabeçalhos PHP

146

Eu tenho um script PHP simples que estou tentando fazer uma solicitação CORS entre domínios:

<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: *");
...

Ainda recebo o erro:

O campo de cabeçalho da solicitação X-Requested-Withnão é permitido porAccess-Control-Allow-Headers

Falta alguma coisa?

Machavity
fonte

Respostas:

59

Access-Control-Allow-Headersnão permitir o *valor aceito, consulte a documentação do Mozilla aqui .

Em vez do asterisco, você deve enviar os cabeçalhos aceitos (primeiro X-Requested-Withcomo o erro indica).

KARASZI István
fonte
289

Lidar com solicitações CORS corretamente é um pouco mais envolvido. Aqui está uma função que responderá mais completamente (e adequadamente).

/**
 *  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!";
}
slashingweapon
fonte
32
Observe que o envio do valor de origem HTTP de volta como origem permitida permitirá que qualquer pessoa envie solicitações para você com cookies, roubando potencialmente uma sessão de um usuário que fez login no seu site e depois visualizou a página de um invasor. Você deseja enviar '*' (que não permitirá cookies, impedindo o roubo de sessões) ou os domínios específicos nos quais deseja que o site funcione.
Jules
1
Acordado. Na prática, você provavelmente não permitiria que nenhum domínio antigo usasse seu serviço CORS, restringiria-o a algum conjunto no qual decidisse confiar.
Slashingweapon
FYI, esta solução só trabalhou para mim em um Linux server, em IIS, por alguma razão simplesmente não funciona, eu não sei se é a minha hospedagem ou apenas não é adequado paraIIS
ncubica
1
Obrigado! Tem que marcar esta resposta como favorita. Pena que não podemos marcar este como uma nova resposta
Ascherer
1
O único que realmente funciona! .. Basta alterar o Acesso-Controle-Permitir-Origem: * Para o Acesso-Controle-Permitir-Origem: {$ _SERVER ['HTTP_ORIGIN']}}
Renan Franca
60

Eu recebi o mesmo erro e o corrigi com o seguinte PHP no meu 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
fonte
35

Muitas descrições em toda a Internet não mencionam que especificar Access-Control-Allow-Originnão é suficiente. Aqui está um exemplo completo que funciona para mim:

<?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
fonte
1
Explique por que não basta e que exemplo mínimo é suficiente.
Halfpastfour.am
Infelizmente, não me lembro exatamente e não tenho tempo agora para investigá-lo novamente, mas, tanto quanto me lembro, havia algumas suposições básicas do lado do servidor da web / navegador que o fizeram não funcionar. Este foi o código mínimo que funcionou para mim.
Csongor Halmai
24

Eu simplesmente consegui fazer com que o dropzone e outro plug-in funcionassem com essa correção (angularjs + php back-end)

 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');

adicione isso no seu upload.php ou para onde você enviaria sua solicitação (por exemplo, se você tiver o upload.html e precisar anexar os arquivos ao upload.php, copie e cole essas 4 linhas). Além disso, se você estiver usando plugins / addons CORS no chrome / mozilla, certifique-se de alterná-los mais de uma vez, para que o CORS seja ativado

Fedeco
fonte
15

Se você deseja criar um serviço CORS a partir do PHP, pode usar este código como a primeira etapa do seu arquivo que lida com as solicitações:

// 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
fonte
8

O CORS pode se tornar uma dor de cabeça, se não entendermos corretamente seu funcionamento. Eu os uso em PHP e eles funcionam sem problemas. referência aqui

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");
shades3002
fonte
7

Esse código funciona para mim ao usar angular 4 como lado do cliente e PHP como lado do servidor.

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

isso deve funcionar

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

adicione este código em .htaccess

adicione chaves de autenticação personalizadas no cabeçalho, 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
fonte
-1

No Windows, cole este comando na janela de execução por algum tempo para testar o código

chrome.exe --user-data-dir = "C: / Chrome dev session" --disable-web-security

Fazil Raza
fonte
Desabilitar a segurança da web do navegador, mesmo que temporariamente, é uma péssima idéia
Machavity