使用 Laravel Passport with Tenancy for Laravel 的问题

Issue using Laravel Passport with 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();,我会得到属于相应租户的正确用户。

我尝试按照他们文档中的 Integration with 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:

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 中声明)。这对我来说很好,如果我遇到任何问题,我会更新我的解决方法。