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?

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).


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!";
}

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

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

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


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

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

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: *");

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

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"

-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


Desabilitar a segurança da web do navegador, mesmo que temporariamente, é uma péssima idéia
Machavity
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.