Заголовки запросов перекрестного происхождения (CORS) с заголовками PHP

#php #jquery #ajax #codeigniter

#php #javascript #xmlhttprequest #cors

Вопрос:

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

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

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

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

Что-нибудь, что я упускаю?

Комментарии:

1. 2022 и верхний ответ действительно работает (на некоторых версиях PHP), приятно.

Ответ №1:

Правильная обработка запросов 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!";
}
 

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

Сверьте заголовок HTTP_ORIGIN со списком утвержденных источников.

Если источник не утвержден, вам следует отклонить запрос.

Пожалуйста, прочитайте спецификацию.

TL; DR

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

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

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

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

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

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

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

Комментарии:

1. Обратите внимание, что отправка исходного значения HTTP в качестве разрешенного источника позволит любому отправлять вам запросы с помощью файлов cookie, что потенциально может привести к краже сеанса у пользователя, который вошел на ваш сайт, а затем просмотрел страницу злоумышленника. Вы либо хотите отправить ‘*’ (который запретит использование файлов cookie, тем самым предотвратив кражу сеанса), либо конкретные домены, для которых вы хотите, чтобы сайт работал.

2. Согласен. На практике вы, вероятно, не разрешили бы какому-либо старому домену использовать ваш сервис CORS, вы бы ограничили его некоторым набором, которому вы решили доверять.

3. Единственное, что действительно работает !.. Просто измените Access-Control-Allow-Origin: * НА Access-Control-Allow-Origin: {$_SERVER[‘HTTP_ORIGIN’]}

4. Безоговорочно разрешая использование любого источника ACAC: true , вы, по сути, выбрасываете Политику одного и того же источника в окно. Этот ответ — ужасный совет с точки зрения безопасности, и он должен быть предан забвению.

5. За использование проголосовали $_SERVER['HTTP_ORIGIN'] против . Это огромный риск для безопасности.

Ответ №2:

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

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

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

header("Access-Control-Allow-Headers: X-Requested-With");
 

Комментарии:

1. должны ли эти три строки добавляться в начало файла PHP? Например, <?php header(‘Access-Control-Allow-Origin: *’); header(‘Access-Control-Allow-Methods: GET, POST’); header(«Access-Control-Allow-Headers: X-Requested-With»);

Ответ №3:

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

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

Обновить:

* теперь принято есть Access-Control-Allow-Headers .

Согласно MDN Web Docs 2021:

Значение * учитывается только как специальное подстановочное значение для запросов без учетных данных (запросов без HTTP-файлов cookie или информации об аутентификации HTTP). В запросах с учетными данными оно обрабатывается как буквальное имя заголовка * без специальной семантики. Обратите внимание, что заголовок авторизации не может быть подстановочным и всегда должен быть указан явно.

Комментарии:

1. По состоянию на 2021 год, похоже * , что теперь это принято в соответствии с документами MDN.

Ответ №4:

Во многих описаниях, размещенных в Интернете, не упоминается, что указания 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. Пожалуйста, объясните, почему этого недостаточно и какого минимального примера достаточно.

2. К сожалению, я точно не помню, и сейчас у меня нет времени исследовать это снова, но, насколько я помню, были некоторые основные предположения со стороны веб-сервера / браузера, из-за которых он не работал. Это был минимальный код, который работал для меня.

3. если уже отправлено в виртуальный хост apache .. тогда работает только этот код ..if ($_SERVER[‘REQUEST_METHOD’] === ‘OPTIONS’) {die(); }

4. По сути, здесь говорится, что этого достаточно, только не в том случае, если метод запроса — «параметры».


Ответ №5:

Мне просто удалось заставить dropzone и другой плагин работать с этим исправлением (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');
 

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

Комментарии:

1. нужно ли нам разрешать исходный заголовок? звучит странно

Ответ №6:

Если вы хотите создать службу 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
 

Комментарии:

1. Это решает мою проблему — по-видимому, мой веб-сервис PHP не может правильно обработать запрос ПАРАМЕТРОВ, на который полагается мой интерфейс Angular перед отправкой запроса POST. Спасибо!

Ответ №7:

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

Комментарии:

1. Я использовал это в Codeigniter 4.1.3, и это работает

Ответ №8:

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

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

Комментарии:

1. Будьте осторожны при использовании подстановочного знака «*». Никогда не открывайте его, если это не то, что вы действительно собираетесь сделать. Что касается тестирования вашего приложения angular, укажите localhost: 4200 , и оно будет работать, оставаясь при этом более безопасным.

2. Протестировано на сервере LAMP под управлением PHP 7.4.x

Ответ №9:

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

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

Комментарии:

1. Это очень хорошо работало на VUE XAMPP (PHP)

Ответ №10:

добавьте этот код в .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"
 

Ответ №11:

Я использовал эти 5 заголовков и после этого решил ошибку cors (серверная часть: PHP, интерфейс: VUE JS)

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