lets-code

lets-code

  • Главная
  • css/html/js
  • php
  • seo
  • Разное
  • Уроки
  • Полезное
  • Книги

Кроссдоменные запросы (CORS) простая реализация

07.05.2017 в 14:14 yazu php,Уроки 8193
CORSlaravelphpурок

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

Для начала, рассмотрим пример:

У вас есть сайт «А», на пример, реализованный на Laravel и vue.js, который реализует определенную логику работы с какими-либо данными. Сейчас вы, в рамках одного сервиса (в данном случае, несколько микро сервисов решающих разные задачи для одного большого проекта), создаете сайт «Б», которому необходимо работать с той же базой данных и использовать часть функционала сайта «А».

Как решить этот вопрос? Естественно вы можете повторно реализовать необходимый функционал на сайте «Б» и подключиться к базе сайта «А». Но в этом есть свои существенные минусы, как минимум это:

  1. Вы, в рамках одной системы, дублируете код, который вы написали ранее.
  2. Вы используете прямой доступ к БД из двух разных мест, это существенно усложнит поиск ошибок, если такие возникнут и такой подход считается далеко не «лучшей практикой».

Так же, у вас есть ещё один вариант реализации (да, это первое, что пришло вам в голову) — jsonp. Но особенности этого метода заключаются в некоторой сложности реализации:

  1. Высокие требования к безопасности данного подхода
  2. Требования к изменению кода уже написанного ранее для сайта «А».
  3. Метод позволят только получить данные, если вам, к примеру требуется отправить информацию методом POST, при помощи jsonp вы этого сделать не сможете.
  4. Уязвимость к инъекциям — вы должны полностью доверять серверу, от которого получаете данные, ведь вы будете выполнять весь код, который вам от него приходит.

Но есть вариант лучше, проще, так как не требует внесения изменений на сайте «А» и является более безопасным подходом, это кроссдоменные запросы или CORS — Cross-origin resource sharing (в переводе: совместное использование ресурсов между разными источниками).

Суть метода очень проста: для того, чтобы серверу «А» получить или отправить данные на сервер «Б», достаточно на сервере «Б» установить «разрешение» на получение и ответ на запросы с сервера «А». Делается это следующим образом: в заголовках ответа на сервере «Б» вам необходимо установить следующие записи:

1
2
3
4
5
6
7
8
//Сначала разрешим принимать и отправлять запросы на сервер А
header('Access-Control-Allow-Origin: www.serverAdomain.ru');
//Установим типы запросов, которые следует разрешить (все неуказанные будут отклоняться)
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
//Разрешим передавать Cookie и Authorization заголовки для указанновго в Origin домена
header('Access-Control-Allow-Credentials: true');
//Установим заголовки, которые можно будет обрабатывать
header('Access-Control-Allow-Headers: Authorization, Origin, X-Requested-With, Accept, X-PINGOTHER, Content-Type');

В большинстве случаев, для выполнения простых кроссдоменных запросов вам будет достаточно установить только заголовок Origin, но если вы пишите полноценное SPA приложение, которое требует авторизации, хранения Cookies и пересылки данных в обе стороны, вам понадобятся все указанные заголовки.

В Laravel очень удобно предусмотрен механизм обработки запросов при помощи middleware, если вы используете данный фреймворк вы можете легко создать middleware для обработки CORS запросов. Ниже приведен пример такого способа:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?php
 
namespace App\Http\Middleware;
 
use Closure;
use Illuminate\Http\Response;
 
class Cors
{
    /**
     * Массив доменов, с которых будем принимать запросы.
     *
     * @var array
     */
    protected $domains = [
        'http://serverA.ru',
        'http://serverB.ru',
        'http://serverC.ru',
    ];
 
    /**
     * Метод, который обрабатывает все запросы, приходящие на сервер.
     *
     * @param \Illuminate\Http\Request $request
     * @param Closure $next
     * @return Response
     */
    public function handle($request, Closure $next)
    {
        // проверим, присутствует ли заголовок HTTP_ORIGIN в запросе
        // и разрешен ли домен
        $origin = $request->headers->get('Origin');
        if(!$origin || !in_array($origin, $this->domains, true)) {
            return new Response('Forbidden', 403);
        }
 
        //если есть, то устанавливаем нужные заголовки
        return $next($request)
            ->header('Access-Control-Allow-Origin', $origin)
            ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
            ->header('Access-Control-Allow-Credentials', 'true')
            ->header(
                'Access-Control-Allow-Headers',
                'Authorization, Origin, X-Requested-With, Accept, X-PINGOTHER, Content-Type'
            );
    }
}

Через данный middleware, как через фильтр, будут проходить все запросы, которые приходят на сервер, и он будет обрабатывать только те запросы, которые приходят с одного из доменов, который присутствует в массиве
$domains.

Можно немного модифицировать метод и получать массив $domains из базы данных, а добавление новых доменов вывести в административную часть сайта и таким образом дать возможность администратору сайта самому добавлять необходимые домены и не отвлекать вас от работы.

Таким простым способом вы можете использовать одну серверную часть для нескольких ваших приложений, делая кроссдоменные запросы.

comments powered by HyperComments

Понравилась статья? Поделитесь ею:

Предыдущий пост: instagram виджет без backend’а, только javascript
Следующий пост: Красивые треугольники на чистом CSS без костылей
Поиск по сайту
Свежие записи
  • Адаптивная masonry сетка на JS и CSS Grid
  • Пример простого приложения на PhoneGap и Vue.js
  • 7 Material Design CSS фреймворков на 2017 год
  • dynamicsjs — красивые анимации, основанные на законах физики
  • Делаем адаптивные табы без javascript и грязных хаков
Метки
ajax API bitrix clip-path cms CORS css css filter css shape debug flexbox framework frontend html instagram javascript jquery laravel mysql o'reilly php seo ui ux wordpress Яндекс подборка сервис урок хостинг
lets-code.ru © 2016
developed by Yazu
Предложить новость

Обратная связь