Я пытаюсь взломать приложение с несколькими арендаторами баз данных, используя laravel. Пройдя много статей в Интернете, я теперь понимаю, что существуют разные подходы к архитектуре базы данных.
tenant_id
внешний ключ для разделения записей арендатораПроект, над которым я работаю, требует, чтобы у каждого арендатора была своя собственная база данных в целях безопасности. Сейчас я пытаюсь вручную взломать установку Laravel 5, чтобы добиться этого, но я не профессионал и вижу некоторые неудачи.
Итак, я начал с создания миграции для основной БД, в которой будут храниться все арендаторы. Я создал эту миграцию в папке с именем main
в папке миграций. Схема выглядит так:
Schema::create('tenants', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->text('description');
$table->string('logo');
$table->string('username');
$table->timestamps();
});
Затем я создал файлы миграции для баз данных клиентов и поместил их в tenants
папка внутри папки миграций. Схема выглядит так:
Таблица пользователей:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
Таблица ролей:
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->sting('name');
$table->timestamps();
});
И стержень между двумя:
Schema::create('role_user', function (Blueprint $table) {
$table->increments('id');
$table->integer('role_id')->unsigned();
$table->foreign('role_id')->refernces('id')->on('roles');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->refernces('id')->on('users');
$table->timestamps();
});
На этом этапе я начал с начальных файлов, которые должны были создать несколько поддельных арендаторов, а затем для каждого арендатора запустил миграцию, чтобы создать базу данных арендатора. Исходный файл выглядит так:
public function run()
{
$faker = Faker::create();
// Fetching all tenants
$tenants = App\Tenant::all();
// Deleting their databases
$tenants->each(function($tenant){
DB::statement('DROP DATABASE IF EXISTS ' . $tenant->username);
DB::statement('DROP USER IF EXISTS ' . $tenant->username);
});
// Truncating the tenants table itself
DB::table('tenants')->truncate();
for($i = 0; $i < 3; $i++){
$company = $faker->company();
$description = $faker->text();
$logo = $faker->imageUrl(50, 50);
$username = str_random(20);
Tenant::create([
'name' => $company,
'description' => $description,
'logo' => $logo,
'username' => $username,
]);
// Creating a new user by the username of the tenant
// Also giving him privileges on the database by the same name
DB::statement("CREATE USER " . $username . "@'localhost' IDENTIFIED BY 'admin12345';");
DB::statement("GRANT ALL PRIVILEGES ON *.* TO " . $username . "@'localhost';");
DB::statement('CREATE DATABASE ' . $username);
// Todo: Save these database credentials somewhere
// Todo: Run migration on the databases created
}
}
На данный момент я запутался, как хранить учетные данные БД для каждого пользователя? Я имею в виду, что сейчас я жестко кодирую пароль для каждой базы данных, но это скоро изменится, и у каждого пользователя будет уникальный пароль. Так стоит ли хранить пароль в основной базе данных? Я имею в виду, что могу зашифровать и сохранить его, а затем, когда мне нужно подключиться к БД, я могу взять имя пользователя арендатора и расшифрованный пароль для подключения к БД. Это хороший подход?
Кроме этого, я также запутался в том, как динамически подключаться к БД и выполнять миграции для таблиц клиентов. Я знаю, что могу вызывать ремесленные команды для запуска миграций, но как сначала подключиться к БД?
Меня также смущает вопрос о том, как проверить, какой пользователь вошел в систему. Я имею в виду, что у каждого арендатора есть свои пользователи. Поэтому, когда пользователь входит в систему, я также спрашиваю его имя пользователя-арендатора, чтобы я знал, к какой базе данных подключаться, и затем аутентифицировал их в таблице пользователей в ней.
Но опять же меня смущает, что если я даже на правильном пути с таким подходом?
Поэтому моя главная проблема сейчас — это динамическое подключение к другой базе данных. Как мне это сделать?
Модель Eloquent имеет метод, называемый setConnection
что вы можете использовать, чтобы установить соединение.
Таким образом, у вас может быть база данных, в которой вы храните настройки для каждого клиента, а затем извлекаете эти настройки и подключаете базу данных.
$nameKey = 'NameOfConnection';
$dataSync = AtlasBases::find($id_client);
Config::set('database.connections.' . $nameKey, array(
'driver' => 'mysql',
'host' => $dataSync->site_db_server,
'database' => $dataSync->site_db_base,
'username' => $dataSync->site_db_user,
'password' => $dataSync->site_db_password,
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => '',
));
# And set the new connection to my models
$imobModel = new ImobImoveis;
$imobModel->setConnection($nameKey);
Посмотрите на следующие ссылки:
И вот демонстрационный репозиторий, который использует подобное решение: https://github.com/uxweb/laravel-multi-db
Других решений пока нет …