php - 使用 Laravel Passport 和 Tenancy for Laravel 的问题
问题描述
我正在使用Tenancy For Laravel创建一个基于子域的多租户 laravel 项目,除了尝试使用 Passport 验证我的 API 请求时,一切正常。现在它的工作原理是我有一个主数据库(多租户),我在其中声明租户并指定相应的子域,然后每个租户都有自己的数据库(tenantfoo)。我通过了 Auth::check 并在正确的数据库中检查了凭据,但是当我尝试创建令牌时,它停止使用租户数据库(tenantfoo)并尝试在主数据库(多租户)中创建令牌并给出以下异常。
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'multi-tenant.oauth_personal_access_clients' doesn't exist
(SQL: select exists(select * from `oauth_personal_access_clients`) as `exists`)
前提是如果我确实尝试让用户使用,User::all();
我会得到属于相应租户的正确用户。
我尝试从他们的文档中遵循与 Passport 的集成,但对我来说没有用..
那么我要问的是,有没有办法手动创建我的令牌?
我试过这样做但仍然给出同样的错误
public function loginManual() {
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
$token = Auth::user()->createToken('Laravel Password Grant Client')->accessToken;
$response = ['token' => $token];
return $response
} else {
$response = ["message" => "Password mismatch"];
return $response
}
}
下面附上一些代码,请随意询问任何未提供的内容。
AppServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
use Laravel\Passport\Passport;
use Stancl\Tenancy\Middleware\InitializeTenancyByDomain;
use Stancl\Tenancy\Middleware\PreventAccessFromCentralDomains;
use Illuminate\Support\Facades\Route;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
Passport::ignoreMigrations();
Passport::routes(null, ['middleware' => [
// You can make this simpler by creating a tenancy route group
InitializeTenancyByDomain::class,
PreventAccessFromCentralDomains::class,
]]);
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Passport::loadKeysFrom(base_path(config('passport.key_path')));
Schema::defaultStringLength(191);
}
}
AuthServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
use Laravel\Passport\Passport;
use Stancl\Tenancy\Middleware\InitializeTenancyByDomain;
use Stancl\Tenancy\Middleware\PreventAccessFromCentralDomains;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication/authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Passport::routes();
}
}
解决方案
所以我最终创建了一个中间件,并在运行中手动将数据库更改为正确的。并将中间件添加到Passport::routes();
启动中。这样,所有护照路线都将根据正确的数据库进行检查。
中间件类:
class ChangeDatabaseConnection
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
if ($request->tenant != 'www' && $request->tenant != NULL) {
$db_name = 'tenant'. $request->tenant;
\DB::disconnect();
\Config::set('database.connections.mysql.database', $db_name);
\DB::reconnect();
$db = \Config::get('database.connections.mysql.database');
return $next($request);
} else {
$url = $request->url();
$parsedUrl = parse_url($url);
$host = explode('.', $parsedUrl['host']);
$subdomain = $host[0];
if ($subdomain != NULL && $subdomain != 'www') {
$db_name = 'tenant'. $subdomain;
\DB::disconnect();
\Config::set('database.connections.mysql.database', $db_name);
\DB::reconnect();
$db = \Config::get('database.connections.mysql.database');
return $next($request);
}
}
return $next($request);
}
}
护照路线声明(AuthServiceProvider):
Passport::routes(null, ['middleware' => ['pre-db']]);
我只在提供租户(不是“www”)时更改数据库,否则使用主数据库(在 .env 中声明)。这对我来说很好,如果我遇到任何问题,我会用我如何解决它们来更新我的答案。
推荐阅读
- python - 响应 json 结果中缺少数据
- prolog - 使用 Prolog 查找在特定公司工作的员工列表
- javascript - 如何在卡片中显示 API 数据(图像、名称、详细信息)?
- c++ - Visual Studio Code 上的 GDB 尝试从不存在的目录中读取标头
- r - 如果其他列包含特定值,则日期的频率计数
- sql - 如何从 sqlx 获取最后插入的行的 id
- javascript - 如何使用 Jest 和 ReactJs 测试 onClose 道具
- assembly - 切换到保护模式后如何正确跳转到内核
- firebase - 如何从firebase地图数据Flutter中创建一个按int值排序的排序列表
- redirect - 用户重定向到 UI5 中的应用程序根路径