Кроссдоменная авторизация на yii2. Часть 1

Рассмотрим механизм реализации кроссдоменной авторизации на yii2. Вопрос достаточно обширный, поэтому статья разделена на несколько частей. Приступим!

Наша реализация (сама система авторизации) будет расширяемой и сможет авторизовывать любые CMS и фреймворки, естественно при условии, что будет созданы и настроены соответствующие классы (об этом попозже). Сразу развеем вопросы по поводу oauth2 - данная реализация очень удобна, однако если у Вас есть работающие годами сайты, со своими базами пользователей, и Вы хотите упростить задачи работы с пользовательскими базами, то добро пожаловать.

Поскольку система сможет поддерживать авторизацию практически любых CMS, то не обойтись без API, соответсвенно требуется реализовать фильтры CORS (фильтрация междоменных запросов) и RateLimiter (ограничение количества запросов по времени).

Механика авторизации будет основана на сессиях и cookie. Возможны реализации с внедрением iframe, перенаправлениями (как на битбакете) или внедрением модальных окон на подключаемые сайты.

Плюсы данного подхода:

  • Подключаемые сайты могут быть на разных CMS и фреймах
  • Сайты могут быть расположены на разных серверах и иметь разные доменные имена
  • Базы данных подключаемых сайтов также могут быть различными
  • При вводе логина и пароля авторизация проводится на всех подключенных сайтах
  • На подключенных сайтах не надо менять ролевые системы, структуру базы и т.д., достаточно подключить скрипты и модальные окна (ссылки или iframe)
  • Возможность управления пользователями и профилями из одного сайта

Почему в качестве системы авторизации выбран yii2? чисто субъективные причины - мне удобнее на нем писать. Варианты с реализацией системы авторизации на других фреймворках - на ваш выбор, symfony или laravel - отличия в механике будут незначительными.

Для начала надо определить механику работы с междоменной защитой, будем предполагать что запросы к АПИ могут присылать только разрешенные доменные имена (или IP).

Добавим миграцию

$this->createTable('{{%sites}}', [
    'id' => $this->primaryKey(),
    'url' => $this->string()->notNull()->comment('Ссылка на сайт'),
    'name' => $this->string()->notNull()->comment('Машинное имя'),
    'description' => $this->string()->notNull()->comment('Описание'),
    'configuration' => $this->string()->notNull()->comment('Дополнительная конфигурация')
]);

Под машинным именем будем понимать уникальное название сайта, в конфигурации будем хранить json строку с возможными нужными данными (ключи и уникальные параметры каждого сайта).

Далее настроим CORS, для этого в котнтроллере опишем поведение:

protected $allowedSites = [];

public function __construct($id, $module, $config = [])
    {
        // тут заполняем массив $allowedSites
        parent::__construct($id, $module, $config);
    }

public function behaviors()
{
    return [
        'corsFilter' => [
            'class' => Cors::className(),
            'cors' => [
                'Access-Control-Allow-Origin' => $this->allowedSites,
                'Access-Control-Allow-Credentials' => true,
                'Access-Control-Request-Method' => ['POST'],
            ],
        ],
    ];
}

Вернемся к вопросу общей схемы кроссдоменной авторизации, возможны такие варианты как:

  • встраивание модальных окон
  • перенаправление на сайт авторизации и обратный редирект в случае успеха
  • встраивание iframe

Плюсы и минусы, а также реализации - в следующих частях...

{{ message }}

{{ 'Comments are closed.' | trans }}