У вас нет разрешения на доступ к API. OpenCart

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Содержание

  • 1. Простой случай

  • 2. Случай клиента

  • 3. В чем проблема?

  • 4. Решение проблем

  • 5. Итог

Простой случай

Как правило проблема с доступом к API OpenCart возникает когда не настроен доступ по API.

IP адрес еще не добавлен в список разрешенных для доступа по API
IP адрес еще не добавлен в список разрешенных для доступа по API

Для решения этой проблемы нужно пройти в админке в Система-Пользователи-API, зайти в нужный объект списка и добавить свой IP адрес в список.

Добавляем свой IP адрес в список разрешенных для доступа по API
Добавляем свой IP адрес в список разрешенных для доступа по API

Либо на странице, с сообщением о проблеме с API просто нажать на кнопку Добавить IP-адрес и обновить страницу.

Но у нашего клиента на OpenCart 2.3 было не все так просто ...

Случай клиента

Перед началом разработки модуля клиент сообщил мне, что в админке на странице редактирования заказа у него часто/рандомно не работает изменение заказа: У вас нет разрешения на доступ к API!

А как позже выяснилось, такая проблема у клиента на 2 сайтах, где используется одна и та же версия OpenCart 2.3, сайты размещены у одного и того же хостера.

Сообщение которое часто вылезало на странице редактирования заказа
Сообщение которое часто вылезало на странице редактирования заказа

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

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

Стоит уточнить, что интерфейс редактирования заказа во многом построен на Ajax API OpenCart, с использованием авторизации и получением токена для доступа к API.

Первым делом я перепроверил ajax запросы на корретность работы, как на клиенте так и на сервере. Токен на клиенте есть, проверка токена и авторизация по токену на сервере есть. Все также как и у API запросов, но не работает ...

В чем проблема?

В другой статье мы уже вкратце разбирали Ajax API, а теперь копнем глубже.

Посмотрим контроллер catalog/controller/api/login.php (запрос получения токена для работы с API /index.php?route=api/login), в случае валидного API key и наличия в этой группе IP адреса выполняющего (того кто делает запрос), данный запрос стартует новую сессию с именем api с единственным ключом api_id:

$session_id_new = $this->session->createId();
$this->session->start('api', $session_id_new);
$this->session->data['api_id'] = $api_info['api_id'];

Затем посмотрим catalog/controller/startup/session.php (это первичный контроллер, который запускается при любом запросе в catalog, до основного контроллера), здесь при наличии токена полученного в предыдущем запросе происходит старт сессии с именем api:

$this->session->start('api', $query->row['session_id']);

А теперь пройдем в файл с классом сессии system/library/session.php и смотрим метод start:

public function start($key = 'default', $value = '') {
if ($value) {
    $this->session_id = $value;
} elseif (isset($_COOKIE[$key])) {
    $this->session_id = $_COOKIE[$key];
} else {
    $this->session_id = $this->createId();
}   
 
if (!isset($_SESSION[$this->session_id])) {
    $_SESSION[$this->session_id] = array();
}
 
$this->data = &$_SESSION[$this->session_id];
 
//...
}

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

Вспоминаем что API запросы OpenCart проверяют валидность доступа в catalog контекст по токену следующим образом:

if (!isset($this->session->data['api_id'])) {
  $json['error']['warning'] = $this->language->get('error_permission');
} else {
  ...
}

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

Для того чтобы понять в чем проблема, можно попробовать записывать данные $_SESSION в файл в запросе получения токена (после его получения), и при первом API запросе в файле catalog/controller/startup/session.php прямо перед или после старта api сессии.

В итоге я увидел что:

Сессия с session_id создается на этапе авторизации и в нее записывается один единственный ключ api_key, но уже при следующем запросе к API, массив данных сессии с этим session_id пуст, но заполняется при отработке всех контроллеров указанных в массиве action_pre_action(в файле system/config/catalog.php) и данные сессии сохраняются.

Однако при этом в нем отсутствует ключ api_id, без которого дальнейшая работа с API невозможна и поэтому мы видим сообщение: У вас нет разрешения на доступ к API!

Решение проблем

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

После обращения клиента в ТП хостинга, проблема исчезла на некоторое время (в это же время я пытался решить ее самостоятельно, но безуспешно, ибо не воспроизводилось), а потом благополучно, примерно через сутки, проблема вернулась.

Повторный дебаг $_SESSION не дал результатов, все также: при запросе авторизации создавалась новая сессия с ключом api_id, а при следующем обращении к API эта новая сессия была пуста.

Понимая что данные сессии не могут сохранится в $_SESSION при запросе авторизации снова смотрим catalog/controller/startup/session.php и видим запрос к БД:

$query = $this->db->query("SELECT DISTINCT * FROM `" . DB_PREFIX . "api` `a` LEFT JOIN `" . DB_PREFIX . "api_session` `as` ON (a.api_id = as.api_id) LEFT JOIN " . DB_PREFIX . "api_ip `ai` ON (as.api_id = ai.api_id) WHERE a.status = '1' AND as.token = '" . $this->db->escape($this->request->get['token']) . "' AND ai.ip = '" . $this->db->escape($this->request->server['REMOTE_ADDR']) . "'");

Если этот запрос возвращает не пустой массив, значит можно считать что авторизация прошла успешно, а среди выбранных из БД данных есть api_id.

В catalog/controller/startup/session.php сразу после старта сессии пишем:

if ($query->num_rows) {
    $this->session->start('api', $query->row['session_id']);
 
    //это может решить проблему с доступом по апи
    $this->session->data["api_id"] = $query->row["api_id"];
     
    //...
}

И проблема У вас нет разрешения на доступ к API! решена!

Для решения проблемы У вас нет разрешения на доступ к API! в данном случае достаточно после старта сессии в catalog/controller/startup/session.php вставить в массив сессии ключ api_id$this->session->data["api_id"] = $query->row["api_id"];

Для убедительности я провел тест: получил ошибку У вас нет разрешения на доступ к API!, а затем применил описанное выше решение и не перезагружая страницы (где была ошибка) провел несколько ajax запросов к API OpenCart, которые прошли успешно.

Итог

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

Автор: Виталий Бутурлин

Источник: https://habr.com/ru/post/548324/


Интересные статьи

Интересные статьи

Ранее мы обсудили доступные «мониторные» наушники, колонки для мультимедиа и настоящие «студийники» для работы со звуком. Сегодня — продолжаем цикл материалов об универса...
Современные системы контроля доступа научились узнавать сотрудников по лицу. Это удобно: не нужно носить на шее бейдж с RFID-чипом и прикладывать его к считывателю у каждой закрытой двери...
В настоящее время практически каждая компания в мире собирает статистику о действиях пользователя на web ресурсе. Мотивация понятна — компании хотят знать как используется их продукт/...
XMage — клиент-серверное приложение для игры в Magic: The Gathering (MTG). XMage начал развиваться еще в начале 2010 года. За это время было выпущено 182 релиза, набралась целая арм...
1С Битрикс: Управление сайтом (БУС) - CMS №1 в России по версии портала “Рейтинг Рунета” за 2018 год. На рынке c 2003 года. За это время БУС не стоял на месте, обрастал новой функциональностью...