Web

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

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

<?php

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

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

...

 

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

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

 

Что-то я делаю неправильно?

 

Ответ 1

Access-Control-Allow-Headers не допускает «приемлемого значения.

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

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

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

 

 

Ответ 2

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

/**

 *  Пример CORS-совместимого метода. Он разрешает любые запросы GET, POST или OPTIONS из любого

 * места.

 *

*/

function cors() {

    if (isset($_SERVER['HTTP_ORIGIN'])) {

        header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");

        header('Access-Control-Allow-Credentials: true');

        header('Access-Control-Max-Age: 86400');    // кэш на 1 день

    }

    if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {

        if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))

            // можно использовать в PUT, PATCH, HEAD и т. п.

            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 "Это CORS!";

}

 

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

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

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

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

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

 

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

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

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

 

Ответ 3

Многие описания не упоминают, что элементов 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);

 

Ответ 4

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

if(isset($_SERVER["HTTP_ORIGIN"])) {

    header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");

} else {

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

}

header("Access-Control-Allow-Credentials: true");

header("Access-Control-Max-Age: 600");    // кэш на 10 минут

if($_SERVER["REQUEST_METHOD"] == "OPTIONS") {

    if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"]))

        header("Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT");

    if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"]))

        header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");

    exit(0);

}

Схожие статьи

Web

Как определить функцию PHP при нажатии кнопки на форме

Web

Отправка электронной почты с помощью SMTP-сервера GMail со страницы PHP

Как обойти reCAPTCHA от Google. Самые простые методы и их реализация
Web

Как обойти reCAPTCHA от Google. Самые простые методы и их реализация

Web

Сохранение формы кнопкой переключения в Laravel 8.x и добавление ее в таблицу enum