Nagłówki żądań między źródłami (CORS) z nagłówkami PHP

146

Mam prosty skrypt PHP, który próbuję wykonać międzydomenowe żądanie CORS:

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

Jednak nadal otrzymuję błąd:

Pole nagłówka żądania X-Requested-Withnie jest dozwolone przezAccess-Control-Allow-Headers

Coś mi brakuje?

Machavity
źródło

Odpowiedzi:

59

Access-Control-Allow-Headersnie pozwala *na akceptowaną wartość, zobacz Dokumentację Mozilli tutaj .

Zamiast gwiazdki należy wysłać zaakceptowane nagłówki (najpierw X-Requested-Withzgodnie z błędem).

KARASZI István
źródło
289

Prawidłowa obsługa żądań CORS jest nieco bardziej skomplikowana. Oto funkcja, która będzie reagować pełniej (i prawidłowo).

/**
 *  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!";
}
cnąca broń
źródło
32
Zwróć uwagę, że wysłanie wartości HTTP Origin z powrotem jako dozwolonego źródła pozwoli każdemu na wysyłanie do Ciebie żądań z plikami cookie, a tym samym potencjalnie kradzież sesji użytkownika, który zalogował się w Twojej witrynie, a następnie wyświetlił stronę atakującego. Chcesz wysłać znak „*” (co uniemożliwi korzystanie z plików cookie, zapobiegając kradzieży sesji) lub określone domeny, dla których witryna ma działać.
Jules,
1
Zgoda. W praktyce prawdopodobnie nie pozwoliłbyś żadnej starej domenie na korzystanie z usługi CORS, ograniczyłbyś ją do jakiegoś zestawu, któremu zdecydowałeś się zaufać.
slashingweapon
FYI, to rozwiązanie działało tylko dla mnie Linux server, IISz jakiegoś powodu po prostu nie działało, nie wiem, czy to mój hosting, czy po prostu nie jest odpowiedniIIS
ncubica
1
Dziękuję Ci! Muszę dodać tę odpowiedź do zakładek. Szkoda, że ​​nie możemy oznaczyć tego jako nowej odpowiedzi
Ascherer
1
Jedyne, co naprawdę działa! .. Po prostu zmień Access-Control-Allow-Origin: * TO Access-Control-Allow-Origin: {$ _SERVER ['HTTP_ORIGIN']}
Renan Franca
60

Otrzymałem ten sam błąd i naprawiłem go za pomocą następującego kodu PHP w moim skrypcie zaplecza:

header('Access-Control-Allow-Origin: *');

header('Access-Control-Allow-Methods: GET, POST');

header("Access-Control-Allow-Headers: X-Requested-With");
Fiach Reid
źródło
35

Wiele opisów w całym Internecie nie wspomina, że ​​określenie Access-Control-Allow-Originnie wystarczy. Oto kompletny przykład, który działa dla mnie:

<?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
źródło
1
Proszę wyjaśnić, dlaczego nie wystarczy i co minimalna przykładem jest mało.
halfpastfour.am
Niestety nie pamiętam dokładnie i nie mam teraz czasu, aby to ponownie zbadać, ale o ile pamiętam, były pewne podstawowe założenia po stronie serwera / przeglądarki, które sprawiły, że nie działała. To był minimalny kod, który działał dla mnie.
Csongor Halmai
24

Po prostu udało mi się uzyskać dropzone i inną wtyczkę do pracy z tą poprawką (backend angularjs + 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');

dodaj to do swojego upload.php lub tam, gdzie chciałbyś wysłać swoje żądanie (na przykład, jeśli masz upload.html i musisz załączyć pliki do upload.php, a następnie skopiuj i wklej te 4 wiersze). Również jeśli używasz wtyczek / dodatków CORS w chrome / mozilla, pamiętaj, aby przełączać je więcej niż jeden raz, aby CORS był włączony

Fedeco
źródło
15

Jeśli chcesz stworzyć usługę CORS z PHP, możesz użyć tego kodu jako pierwszego kroku w pliku, który obsługuje żądania:

// 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
źródło
8

CORS może stać się bólem głowy, jeśli nie zrozumiemy poprawnie jego działania. Używam ich w PHP i działają bez problemów. odniesienie tutaj

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");
odcienie 3002
źródło
7

Tyle kodu działa dla mnie, gdy używam angular 4 jako strony klienta i PHP jako strony serwera.

header("Access-Control-Allow-Origin: *");
Labib Hussain
źródło
3

to powinno działać

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Cache-Control, Pragma, Authorization, Accept, Accept-Encoding");
user8453321
źródło
0

dodaj ten kod w .htaccess

dodaj w nagłówku niestandardowy klucz uwierzytelniania, taki jak 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
źródło
-1

W systemie Windows wklej to polecenie w oknie uruchamiania , aby przetestować kod

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

Fazil Raza
źródło
Wyłączenie zabezpieczeń internetowych przeglądarki, nawet tymczasowe, to straszny pomysł
Machavity