- Enabling Cross-Origin Resource Sharing CORS for PHP
- Setting required headers using PHP
- PHP code to enable CORS
- 5 thoughts on “ Enabling Cross-Origin Resource Sharing CORS for PHP ”
- Как указать Access-Control-Allow-Origin в php?
- Заголовки запросов Cross-Origin (CORS) с заголовками PHP
- Ответ 1
- Ответ 2
- Замечания по безопасности
- Безопасность заголовка
- Ответ 3
- Ответ 4
- Кроссдоменные запросы (CORS) простая реализация
Enabling Cross-Origin Resource Sharing CORS for PHP
This post is an addition to Enabling Cross-Origin Resource Sharing CORS for Apache to show you how to enable Cross-Origin Resource Sharing CORS for PHP. Thus, in case you don’t have access to the .htaccess you can simply enable CORS for PHP using the following steps.
Setting required headers using PHP
As explained in Enabling Cross-Origin Resource Sharing CORS for Apache you need to make sure that responses to cross-domain requests to your server (e.g. through Ajax requests using jQuery) need to include a set of required headers to be accepted by the client browser. These are
- Access-Control-Allow-Origin
- Access-Control-Allow-Methods
- Access-Control-Max-Age
- Access-Control-Allow-Headers
Make sure that Access-Control-Allow-Origin is set a domain value actually allowed by your server. In theory you could use ‘*‘ as well, but some browsers (e.g. Firefox) will simply ignore it and CORS will not work.
PHP code to enable CORS
The following snippet should give you a quick overview about the required HTTP headers to set for CORS to work.
First, it defines a list of allowed origin domains based on regular expressions. This list will be checked against $_SERVER[‘HTTP_ORIGIN’], i.e. the Origin header specified in the client request. If one origin entry from the list matches the required CORS headers will be set. This setup also takes care of the CORS pre-flight request.
// array holding allowed Origin domains $allowedOrigins = array( '(http(s)://)?(www\.)?my\-domain\.com' ); if (isset($_SERVER['HTTP_ORIGIN']) && $_SERVER['HTTP_ORIGIN'] != '') < foreach ($allowedOrigins as $allowedOrigin) < if (preg_match('#' . $allowedOrigin . '#', $_SERVER['HTTP_ORIGIN'])) < header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS'); header('Access-Control-Max-Age: 1000'); header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With'); break; >> >
5 thoughts on “ Enabling Cross-Origin Resource Sharing CORS for PHP ”
[…] Note: Looking for a way to enable CORS for PHP? Have a look at Enabling Cross-Origin Resource Sharing CORS for PHP. […] […] to the reporting graph which is loaded via a http connection set in the configuration, thus causing CORS to kick and prohibit non-safe external […]Как указать Access-Control-Allow-Origin в php?
CORS защищает от запроса не со стороннего сайта (сервера), а со стороннего клиента (браузера).
С помощью CORS мы даем команду «проверь, что ajax запрос был запущен со страницы, которую мы отправили клиенту», т.к. заголовок origin при ajax запросе будет равен домену, на странице которого находился браузер, когда запрос делал. Этот origin в итоге и проверяется на соответствие разрешенному.
То есть он защищает от того, чтобы кто-то на своем сайте не разместил javascript код, который запрашивает данные напрямую с вашего сайта и показывает их на том сайте, как будто данные принадлежали не вам, а другому сайту.
Если вы хотите запретить запрос с другого сайта (сервера), это сделать геморойно и простейшая для реализации защита — это капча на случай если другой сервер делает слишком много запросов = условная проверка IP адреса, который сервер отсылает (но его можно подменить используя прокси, поэтому читай дальше)
Либо это набор букв-цифр (хеш), который ваш же сервер при первом запросе выдает другому серверу позволяя в дальнейшем делать запросы только дублируя выданное вами значение. По сравнению с проверкой IP это дает каждому клиенту свой собственный хеш, тогда как проверка IP может дать неожиданный результат, если люди сидят в компьютерном клубе и 10 человек будут считаться одним.
Первый раз без проверки и отсылается клиенту хеш, а все запросы логики можно сделать потом только если тот сервер передает вам поле, которое вы ему давали (да, это CSRF называется, правда под ним чаще понимают только защиту форм, но принцип именно такой, и можно не только формы проверять, а вообще любые запросы)
После чего по этому полю ведется какой-нибудь подсчет суммы запросов, и если сумма выше N — показ капчи или просто ошибку отдаем вместо данных, это позволяет в некоторой степени быть уверенным, что запрос не делается автоматически и много раз, защищает от DDOS (но тоже частично, т.к. всегда можно сделать запрос с десятка разных компьютеров, все они получат хеш и каждый из них сделает по пару запросов, чтобы не вызвать капчу).
Полная защита может быть так сделана — все запросы логики разрешены только аяксом и стоят корсы, что только с вашего сайта. А все не-ajax и не-GET запросы проверяются на список разрешенных IP адресов. Но даже тут заголовки можно сгенерировать так «как будто это ajax запрос» и все равно пробить.
Заголовки запросов Cross-Origin (CORS) с заголовками PHP
У меня есть простой скрипт PHP, в котором я пытаюсь выполнить междоменный запрос CORS:
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: «);
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: «);
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 недостаточно. Вот полный пример, который мне подходит:
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: «);
> 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: «);
exit(0);
>
Мы будем очень благодарны
если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.
Кроссдоменные запросы (CORS) простая реализация
Несколько раз у меня уже возникала мысль о реализации кроссдоменных запросов между своими сервисами, однако толково настроить получалось плохо. Давайте уже наконец-то разберемся в этой теме.
Для начала, рассмотрим пример:
У вас есть сайт «А», на пример, реализованный на Laravel и vue.js, который реализует определенную логику работы с какими-либо данными. Сейчас вы, в рамках одного сервиса (в данном случае, несколько микро сервисов решающих разные задачи для одного большого проекта), создаете сайт «Б», которому необходимо работать с той же базой данных и использовать часть функционала сайта «А».
Как решить этот вопрос? Естественно вы можете повторно реализовать необходимый функционал на сайте «Б» и подключиться к базе сайта «А». Но в этом есть свои существенные минусы, как минимум это:
- Вы, в рамках одной системы, дублируете код, который вы написали ранее.
- Вы используете прямой доступ к БД из двух разных мест, это существенно усложнит поиск ошибок, если такие возникнут и такой подход считается далеко не «лучшей практикой».
Так же, у вас есть ещё один вариант реализации (да, это первое, что пришло вам в голову) — jsonp. Но особенности этого метода заключаются в некоторой сложности реализации:
- Высокие требования к безопасности данного подхода
- Требования к изменению кода уже написанного ранее для сайта «А».
- Метод позволят только получить данные, если вам, к примеру требуется отправить информацию методом POST, при помощи jsonp вы этого сделать не сможете.
- Уязвимость к инъекциям — вы должны полностью доверять серверу, от которого получаете данные, ведь вы будете выполнять весь код, который вам от него приходит.
Но есть вариант лучше, проще, так как не требует внесения изменений на сайте «А» и является более безопасным подходом, это кроссдоменные запросы или CORS — Cross-origin resource sharing (в переводе: совместное использование ресурсов между разными источниками).
Суть метода очень проста: для того, чтобы серверу «А» получить или отправить данные на сервер «Б», достаточно на сервере «Б» установить «разрешение» на получение и ответ на запросы с сервера «А». Делается это следующим образом: в заголовках ответа на сервере «Б» вам необходимо установить следующие записи: