简体   繁体   English

如何使用SLIM处理多租户?

[英]How to handle multi tenancy with SLIM?

I'm writing an API using SLIM , the goal of that API is create a multi tenant structure. 我正在使用SLIM编写API ,该API的目标是创建多租户结构。 What I did so far is the following: 到目前为止,我所做的是:

First of all, I have created a master database which contains all my customers (who bought my software), for each customer I have a field called CUSTOMER_TOKEN , which represents the credentials to access to the API. 首先,我创建了一个数据库,其中包含我的所有客户(购买了我的软件),对于每个客户,我都有一个名为CUSTOMER_TOKEN的字段,该字段表示访问API的凭据。

Basically, I have two software here: 基本上,我在这里有两个软件:

  • API: read the data from the tenant database. API:从租户数据库中读取数据。
  • Main application: use the API. 主要应用:使用API​​。

Infact, each tenant have a different database, I find this way the best choice for me. 实际上,每个租户都有一个不同的数据库,我发现这种方式对我来说是最佳选择。

Main application get a JWT token sending a request to the API by using the CUSTOMER_TOKEN , eg: 主应用程序获得一个JWT令牌,该令牌通过使用CUSTOMER_TOKENAPI发送请求,例如:

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

the route above will check the customer existence on the master database, if exists, then will return a temporary access token to use the API (JWT). 上面的路线将检查数据库上是否存在客户,如果存在,则将返回一个临时访问令牌以使用API (JWT)。

So far all good. 到目前为止一切都很好。 The main problem come's here. 主要问题来了。 Infact, if the user has got the JWT and the CUSTOMER_TOKEN is valid, then the API should create a connection to the tenant database rather than the master database. 实际上,如果用户拥有JWT并且CUSTOMER_TOKEN有效,则API应该创建与tenant数据库而非数据库的连接。

At the moment, for handle the main connection, I use the SLIM container, in particular: 目前,为了处理主连接,我使用了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;
    };

how can I create a different connection to the tenant database from here? 如何从此处创建与租户数据库的其他连接? Should I use a middleware ? 我应该使用middleware吗? Should I check the requested router to understand if I need the master db or tenant db? 是否应该检查请求的路由器以了解是否需要主数据库或租户数据库?

Take as note that for each tenant I use a name convention structure such as: 请注意,对于每个租户,我使用一个名称约定结构,例如:

app_name-tenant-tenant_name

So I have the prefix as app_name-tenant and then the tenant_name . 所以我的前缀是app_name-tenant ,然后是tenant_name So I only need to get the name of the customer from the master db to assemble the connection. 因此,我只需要从数据库获取customer的名称即可组装连接。

How would you manage this situation? 您将如何处理这种情况? thank you. 谢谢。

For security and practical reasons I would recommend using two different PDO connections (instances). 出于安全和实用的原因,我建议使用两个不同的PDO连接(实例)。 The first connection is for the API (JWT) Auth and the second database connection is for the customer (tenant). 第一个连接用于API(JWT)Auth,第二个数据库连接用于客户(租户)。 You don't need a middleware, because the database connection part of the infrastructure configuration and below the middleware. 您不需要中间件,因为基础结构配置中的数据库连接部分位于中间件下方。

You have multiple options to manage the database connections in combination with a container. 您可以使用多个选项来与容器一起管理数据库连接。

  1. Just add a second alias name for the container entry like pdo2 or db2 or someting similar that makes sense for you. 只需为容器条目添加第二pdo2名,例如pdo2db2或类似的东西对您有意义。
// API
$container['pdo'] = function (Container $container) {
// Customer database
$container['pdo2'] = function (Container $container) {
  1. I hope you use constructor dependency injection . 我希望您使用构造函数依赖项注入 If yes, better define the container entries with a class or the interface name. 如果是,则最好使用类或接口名称定义容器条目。

Example: 例:

class ApiDatabase extends PDO {}

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

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

name convention 名称约定

Now you have a second database connection for the customer, a table prefix is no longer necessary because you already have a technically better separation between the customers. 现在,您已经为客户建立了第二个数据库连接,不再需要表前缀,因为在技术上客户之间已经有了更好的隔离。 Why? 为什么? Database transactions are also completely separated, which has no effect on other customer data (and tables). 数据库事务也完全分开,这对其他客户数据(和表)没有影响。 Database migrations will be easier because you don't have to worry about prefixes. 数据库迁移将更加容易,因为您不必担心前缀。 Now you can deploy new versions per customer without affecting other customers' database. 现在,您可以为每个客户部署新版本,而不会影响其他客户的数据库。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM