Заголовки запросов Cross-Origin (CORS) с заголовками PHP

155

У меня есть простой скрипт PHP, который я пытаюсь выполнить междоменный запрос CORS:

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

Тем не менее, я все еще получаю ошибку:

Поле заголовка запроса X-Requested-Withне разрешеноAccess-Control-Allow-Headers

Что-то мне не хватает?

Мачавити
источник

Ответы:

62

Access-Control-Allow-Headersне допускает *допустимого значения, см. документацию Mozilla здесь .

Вместо звездочки следует отправлять принятые заголовки (сначала, X-Requested-Withкак указано в ошибке).

КАРАСИ Иштван
источник
298

Правильная обработка запросов CORS требует больше усилий. Вот функция, которая ответит более полно (и правильно).

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

Примечания по безопасности

Когда браузер хочет выполнить межсайтовый запрос, он сначала подтверждает, что это нормально, с помощью «предполетного» запроса к URL. Разрешая CORS, вы сообщаете браузеру, что ответы с этого URL-адреса могут быть переданы другим доменам.

CORS не защищает ваш сервер. CORS пытается защитить ваших пользователей, сообщая браузерам, какие ограничения должны быть на обмен ответами с другими доменами. Обычно такой вид обмена категорически запрещен, поэтому CORS - это способ проделать брешь в обычной политике безопасности браузера. Эти дыры должны быть как можно меньше, поэтому всегда сверяйте HTTP_ORIGIN с каким-то внутренним списком.

Здесь есть некоторые опасности , особенно если данные, которые обслуживает URL, обычно защищены. Вы фактически разрешаете контенту браузера, который был создан на каком-то другом сервере, читать (и, возможно, манипулировать) данными на вашем сервере.

Если вы собираетесь использовать CORS, внимательно прочтите протокол (он довольно маленький) и попытайтесь понять, что вы делаете. Для этой цели в примере кода приведен ссылочный URL.

Безопасность заголовка

Было замечено, что заголовок HTTP_ORIGIN небезопасен, и это правда. Фактически, все заголовки HTTP небезопасны для разных значений этого термина. Если заголовок не содержит проверяемую подпись / hmac или весь разговор не аутентифицирован через TLS, заголовки - это просто «то, что мне сказал браузер».

В этом случае браузер сообщает: «объект из домена X хочет получить ответ от этого URL-адреса. Это нормально?» Суть CORS - иметь возможность ответить: «Да, я разрешаю это».

рубящее оружие
источник
34
Обратите внимание, что отправка значения HTTP Origin обратно в качестве разрешенного источника позволит любому отправлять вам запросы с файлами cookie, что потенциально может украсть сеанс у пользователя, который вошел на ваш сайт, а затем просмотрел страницу злоумышленника. Вы либо хотите отправить '*' (что запретит использование файлов cookie, что предотвратит кражу сеанса), либо конкретные домены, для которых вы хотите, чтобы сайт работал.
Жюль
1
Согласовано. На практике вы, вероятно, не позволите любому старому домену использовать вашу службу CORS, вы ограничите ее некоторым набором, которому вы решили доверять.
slashingweapon
1
Спасибо! Надо добавить этот ответ в закладки. Жаль, что мы не можем отметить это как новый ответ
Ascherer
1
Единственное, что действительно работает! .. Просто измените Access-Control-Allow-Origin: * TO Access-Control-Allow-Origin: {$ _SERVER ['HTTP_ORIGIN']}
Ренан Франка
1
Безоговорочно разрешая любое происхождение с ACAC: true, вы, по сути, выбрасываете политику одного и того же происхождения. Этот ответ - ужасный совет с точки зрения безопасности, и его следует предать забвению.
jub0bs,
68

Я получил ту же ошибку и исправил ее с помощью следующего PHP в моем внутреннем скрипте:

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

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

header("Access-Control-Allow-Headers: X-Requested-With");
Фиах Рид
источник
1
Просто и работает!
Саид Джассани,
36

Многие описания в Интернете не упоминают, что уточнения Access-Control-Allow-Originнедостаточно. Вот полный пример, который мне подходит:

<?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
Пожалуйста , объясните , почему это не достаточно , и то , что минимальный пример является достаточно.
halfpastfour.am
К сожалению, я точно не помню, и сейчас у меня нет времени исследовать это снова, но, насколько я помню, были некоторые базовые предположения со стороны веб-сервера / браузера, из-за которых он не работал. Это был минимальный код, который у меня сработал.
Csongor Halmai
24

Мне просто удалось заставить dropzone и другой плагин работать с этим исправлением (angularjs + php backend)

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

добавьте это в свой upload.php или куда вы должны отправить свой запрос (например, если у вас есть upload.html и вам нужно прикрепить файлы к upload.php, затем скопируйте и вставьте эти 4 строки). Также, если вы используете плагины / надстройки CORS в chrome / mozilla, не забудьте переключить их более одного раза, чтобы CORS был включен.

Fedeco
источник
17

Если вы хотите создать службу CORS из PHP, вы можете использовать этот код в качестве первого шага в вашем файле, который обрабатывает запросы:

// 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
Финн Йохансен
источник
9

CORS может стать головной болью, если мы неправильно понимаем его работу. Я использую их в PHP, и они работают без проблем. ссылка здесь

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");
оттенки3002
источник
7

Этот большой код работает для меня при использовании angular 4 на стороне клиента и PHP на стороне сервера.

header("Access-Control-Allow-Origin: *");
Лабиб Хуссейн
источник
5

это должно работать

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Cache-Control, Pragma, Authorization, Accept, Accept-Encoding");
user8453321
источник
0

добавьте этот код в .htaccess

добавить пользовательский ключ аутентификации в заголовок, например 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"
Ракеш Кадас
источник
-4

В Windows вставьте эту команду в окно запуска на время, чтобы проверить код.

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

Фазиль Раза
источник
1
Отключение веб-безопасности вашего браузера, даже временное, - ужасная идея
Machavity