Проблема в реализации паспорта в мультитенантном приложении laravel - PullRequest
0 голосов
/ 13 февраля 2020

Перво-наперво, я использую Hyn-Multi Tenant в моем приложении laravel 6. Там, где есть центральная база данных [connection = system], обрабатывает базу данных нескольких арендаторов. Пока этот пакет мне очень помог, но моему приложению нужна реализация паспорта для apis, которая не описана в пакете.

Однако есть другие учебные пособия , которые требуют реализацию паспорта для пакета Hyn. Я последовал за ними и смог создать токен доступа для каждого пользователя-арендатора.

Это моя конфигурация / аутентификация. php:

return [
'defaults' => [
        'guard' => 'web',
        'passwords' => 'system-users',
    ],


'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'system',
        ],

        'staff' => [
            'driver' => 'session',
            'provider' => 'staff',
        ],

        'api' => [
            'driver' => 'passport',
            'provider' => 'staff',
            'hash' => false,
        ],
        'student' => [
            'driver' => 'passport',
            'provider' => 'student',
            'hash' => false,
        ],
    ],

'providers' => [
        'system' => [
            'driver' => 'eloquent',
            'model' => App\Models\System\User::class,
        ],
        'staff' => [
            'driver' => 'eloquent',
            'model' => App\Models\Tenant\Staff::class,
        ],
        'student' => [
            'driver' => 'eloquent',
            'model' => App\Models\Tenant\Student::class,
        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

В каждой модели моего арендатора используется UsesTenantConnection trait

Это мое промежуточное ПО EnforceTenancy

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Config;


class EnforceTenancy
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        Config::set('database.default', 'tenant');

        return $next($request);
    }
}

Это мой AuthServiceProvider. php

public function boot()
    {
        $this->registerPolicies();

        Passport::routes(null, ['middleware' => 'tenancy.enforce']);


        // FOLLOWING CODE IS HAVING PROBLEM
        //Passport::useTokenModel(OAuthAccessToken::class);
        //Passport::useClientModel(OAuthClient::class);
        //Passport::useAuthCodeModel(OAuthCode::class);
        //Passport::usePersonalAccessClientModel(OAuthPersonalAccessClient::class);

        $this->commands([
            \Laravel\Passport\Console\InstallCommand::class,
            \Laravel\Passport\Console\ClientCommand::class,
            \Laravel\Passport\Console\KeysCommand::class,
        ]);

        \Laravel\Passport\Passport::tokensExpireIn(\Carbon\Carbon::now()->addMinutes(10));
        \Laravel\Passport\Passport::refreshTokensExpireIn(\Carbon\Carbon::now()->addDays(1));
    }

Пока все хорошо, теперь я собираюсь объяснить в пунктах,

  1. Когда я звоню createToken('MyApp'), я могу сгенерировать токен на базе данных арендатора, например:
if (Auth::guard('staff')->attempt(['email' => $request->email, 'password' => $request->password])) {

            $user = Auth::guard('staff')->user();

            $auth_tokens = $user->createToken('MyApp');

            $access_token = $auth_tokens->accessToken;
...
}

, но для доступа к API, защищенному входом в систему, я отправляю носитель токен доступа в заголовке

window.axios
                .get("/api/meta",{
                    headers: fetchAuthHeaders()
                })
                .then(response => {
                    if(true == response.data.status) {
                        var data = response.data.data;
                        this.school.name = data.school_meta.name;
                        this.school.logo = data.school_meta.logo;
                    } else{
                        alert(response.data.message);
                    }

                })

API. php

Route::domain('{hostname}.lvh.me')->group(function () {
    Route::middleware('tenant.exists')->group(function () {
        Route::get('/get-oauth-secret', 'Tenant\MetaController@getOAuthData');
        Route::post('validate-login','Tenant\AuthController@validateLogin');

        Route::middleware(['auth:api'])->group(function (){
            Route::get('meta','Tenant\AuthController@getMetaData'); //this api
        });
    });

});

Я получаю ответ как {"message":"Unauthenticated."}

Как только токен сгенерирован на шаге 1, я копирую этот токен и вставляю его в заголовочный раздел почтальона и раскомментирую пользовательские модели паспортов в AuthServiceProvider. php, как показано ниже

AuthServiceProvider . php

public function boot()
    {
        ...


        // UNCOMMENTED FOLLOWING CUSTOM PASSPORT MODELS
        Passport::useTokenModel(OAuthAccessToken::class);
        Passport::useClientModel(OAuthClient::class);
        Passport::useAuthCodeModel(OAuthCode::class);
        Passport::usePersonalAccessClientModel(OAuthPersonalAccessClient::class);

        ...
    }

Теперь я могу получить доступ к api/meta маршруту, но при входе в систему и создании токена я получаю сообщение об ошибке:

ErrorException: Trying to get property 'id' of non-object in file /home/winlappy1/Desktop/multi_tenancy/vendor/laravel/passport/src/PersonalAccessTokenFactory.php on line 98

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

1 Ответ

0 голосов
/ 17 февраля 2020

Попробуйте добавить

\App\Http\Middleware\EnforceTenancy::class

в начало массива $ middlewarePriority в ядре. php

...