Как справиться с несколькими арендаторами с SLIM? - PullRequest
0 голосов
/ 07 июля 2019

Я пишу API с использованием SLIM , целью этого API является создание мультитенантной структуры. Пока что я сделал следующее:

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

По сути, у меня здесь два ПО:

  • API: чтение данных из базы данных клиентов.
  • Основное приложение: используйте API.

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

Основное приложение получает токен JWT, отправляющий запрос на API с помощью CUSTOMER_TOKEN, например:

http://xxx.xxx.xxx.xxx/v1/auth/login

вышеприведенный маршрут проверит существование клиента в базе данных master , если она существует, затем вернет маркер временного доступа для использования API (JWT).

Пока все хорошо. Главная проблема здесь. Фактически, если у пользователя есть JWT и CUSTOMER_TOKEN допустим, тогда API должен создать соединение с базой данных tenant, а не с master базой данных.

На данный момент для управления основным соединением я использую контейнер SLIM, в частности:

<?php
   use Slim\Container;

   $container = $app->getContainer();

   $container['pdo'] = function (Container $c) {
       $db = $c['settings']['db'];
        $pdo = new PDO(
            "mysql:host=" . $db['host'] . ";dbname=" . $db['dbname'],
            $db['user'],
            $db['pass']
        );
        return $pdo;
    };

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

Обратите внимание, что для каждого арендатора я использую структуру соглашения имен, такую ​​как:

app_name-tenant-tenant_name

Итак, у меня есть префикс app_name-tenant, а затем tenant_name. Поэтому мне нужно только получить имя customer от master db для сборки соединения.

Как бы вы справились с этой ситуацией? спасибо.

1 Ответ

1 голос
/ 08 июля 2019

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

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

  1. Просто добавьте второе псевдоним для записи контейнера, например pdo2 или db2 или что-то подобное, что имеет смысл для вас.
// API
$container['pdo'] = function (Container $container) {
// Customer database
$container['pdo2'] = function (Container $container) {
Надеюсь, вы используете внедрение зависимостей в конструктор .Если да, лучше определить записи контейнера с помощью класса или имени интерфейса.

Пример:

class ApiDatabase extends PDO {}

$container[ApiDatabase::class] = function (Container $container) {
class CustomerDatabase extends PDO {}

$container[CustomerDatabase::class] = function (Container $container) {

соглашение об именах

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...