Множественная аутентификация Laravel Passport с использованием гвардейцев

Можем ли мы использовать паспорт laravel с разными охранниками для аутентификации API для двух разных типов пользователей. Например, у нас есть приложение-драйвер для пользователя-водителя и приложение-поставщик для пользователя-поставщика. У обоих есть разные модели Driver и Vendor. Как мы можем использовать разных охранников для аутентификации обоих типов пользователей с помощью Laravel Passport?


person Ahmar Arshad    schedule 17.10.2018    source источник
comment
Да, я думаю, вы могли бы использовать Laravel Passport для мульти-аутентификации, это не встроенная функциональность, но вы можете написать ее самостоятельно.   -  person chebaby    schedule 17.10.2018


Ответы (4)


Мне удалось создать несколько аутентификаций (с помощью laravel / паспорта) с помощью простого промежуточного программного обеспечения.

Шаг 1. config / auth.php

Добавьте свои пользовательские классы к провайдерам

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

    'api' => [
        'driver' => 'passport',
        'provider' => 'basic_users', // default
    ],        
],

...

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\User::class,
    ],
    'admin_users' => [
        'driver' => 'eloquent',
        'model' => App\AdminUser::class,
    ],
    'basic_users' => [
        'driver' => 'eloquent',
        'model' => App\BasicUser::class,
    ],
],

Очистить кеш через CLI

php artisan config:cache

Шаг 2. Создайте промежуточное ПО

php artisan make:middleware AdminUserProvider

Откройте только что созданное промежуточное ПО в app / Http / Middleware и обновите ручной метод, как показано ниже.

public function handle($request, Closure $next)
{
    config(['auth.guards.api.provider' => 'admin_users']);
    return $next($request);
}

Шаг 3. Зарегистрируйте промежуточное ПО

Добавьте только что созданное промежуточное ПО в $ routeMiddleware

protected $routeMiddleware = [
    ...
    'auth.admin' => \App\Http\Middleware\AdminUserProvider::class,
];

и убедитесь, что он находится на вершине $ middlewarePriority

protected $middlewarePriority = [
    \App\Http\Middleware\AdminUserProvider::class,
    ...
];

Шаг 4. Добавьте промежуточное ПО в маршрут

Route::group(['middleware' => ['auth.admin','auth:api']], function() {

Шаг 5. LoginControllers (AdminUserController и BasicUserController)

public function login()
{
    $validatedData = request()->validate([
        'email' => 'required',
        'password' => 'required|min:6'
    ]);
    // get user object
    $user = AdminUser::where('email', request()->email)->first();
    // do the passwords match?
    if (!Hash::check(request()->password, $user->password)) {
        // no they don't
        return response()->json(['error' => 'Unauthorized'], 401);
    }
    // log the user in (needed for future requests)
    Auth::login($user);
    // get new token
    $tokenResult = $user->createToken($this->tokenName);
    // return token in json response
    return response()->json(['success' => ['token' => $tokenResult->accessToken]], 200);
}

В итоге:

Контроллеры входа в систему используют модели Eloquent для получения объекта пользователя, а затем регистрируют пользователя через Auth :: login ($ user).

Затем для будущих запросов, требующих аутентификации, новое промежуточное ПО изменит поставщика защиты api auth guard на правильный класс.

person rharvey    schedule 06.08.2019
comment
как мы можем обработать следующий запрос, если я хочу просмотреть профиль администратора, как мы можем получить профиль пользователя в следующем запросе? - person kunal; 19.11.2019
comment
Вы можете использовать токен, чтобы определить, кем является пользователь с помощью модели, но я не думаю, что токены доступа должны быть идентификаторами. Они определяют, есть ли у вас доступ к чему-либо или нет. Более вероятно, что вы будете использовать этот код в качестве уровня аутентификации, а затем использовать сгенерированный токен для получения доступа к другой службе. Вы можете передать любую информацию, которую хотите, то есть данные POST. - person rharvey; 20.11.2019
comment
@rharvey благодарит вас за решение, но я получаю сообщение об ошибке: BadMethodCallException: вызов неопределенного метода App \ Merchant :: getAuthIdentifierName () в файле /home/dimonky/api.example.com/vendor/laravel/framework/src/ Illuminate / Support / Traits / ForwardsCalls.php в строке 50 - person mdkamrul; 24.04.2021
comment
Привет @mdkamrul, извиняюсь, прошло много времени с тех пор, как я смотрел на Laravel, поэтому мне трудно помочь. Однако эта ошибка предполагает, что у вас есть класс с именем Merchant, и он ищет метод с именем getAuthIdentifierName, которого не существует. Полагаю, это кастомный код? Возможно, вам нужно проверить конфигурации и убедиться, что вы определили все соответствующие классы. - person rharvey; 26.04.2021

Изменить: теперь в паспорте поддерживается несколько поставщиков услуг защиты. Для получения дополнительной информации перейдите по следующим ссылкам:

Несколько средств защиты аутентификации

Поддержка нескольких охранников


Старый ответ (не рекомендую)

Вот пример auth.php и api.php для начала

config / auth.php

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Defaults
    |--------------------------------------------------------------------------
    */

    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],

    /*
    |--------------------------------------------------------------------------
    | Authentication Guards
    |--------------------------------------------------------------------------
    */

    'guards' => [

        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'driver-api' => [
            'driver' => 'passport',
            'provider' => 'drivers',
        ],

        'vendor-api' => [
            'driver' => 'passport',
            'provider' => 'vendors',
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | User Providers
    |--------------------------------------------------------------------------
    */

    'providers' => [

        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],

        'drivers' => [
            'driver' => 'eloquent',
            'model' => App\Driver::class,
        ],

        'vendors' => [
            'driver' => 'eloquent',
            'model' => App\Vendor::class,
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Resetting Passwords
    |--------------------------------------------------------------------------
    */

    'passwords' => [

        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
        ],

        'drivers' => [
            'provider' => 'drivers',
            'table' => 'password_resets',
            'expire' => 60,
        ],

        'vendors' => [
            'provider' => 'vendors',
            'table' => 'password_resets',
            'expire' => 60,
        ],
    ],

];

routes / api.php

<?php

use Illuminate\Http\Request;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
*/

Route::group(['namespace' => 'Driver', 'prefix' => 'driver/v1', 'middleware' => 'auth:driver-api'], function() {

    // define your routes here for the "drivers"
});

Route::group(['namespace' => 'Vendor', 'prefix' => 'vendor/v1', 'middleware' => 'auth:vendor-api'], function() {

    // define your routes here for the "vendors"
});

Вы должны изменить эти файлы:

Файл: vendor \ laravel \ паспорт \ src \ Bridge \ UserRepository.php

Скопируйте / вставьте getUserEntityByUserCredentials, чтобы сделать его копию, и назовите его getEntityByUserCredentials.

Затем в новой дублированной функции найдите следующее:

$provider = config('auth.guards.api.provider');

И замените его на:

$provider = config('auth.guards.'.$provider.'.provider');

Файл: vendor \ league \ oauth2-server \ src \ Grant \ PasswordGrant.php

in: validateUser метод добавить после $ username и $ password:

$customProvider = $this->getRequestParameter('customProvider', $request);

if (is_null($customProvider)) {
   throw OAuthServerException::invalidRequest('customProvider');
}

И это вместо исходной строки

$user = $this->userRepository->getEntityByUserCredentials(
    $username,
    $password,
    $this->getIdentifier(),
    $client,
    $customProvider
);

После этого вы сможете передать дополнительную пару ключ / значение в свой запрос токена доступа, например:

grant_type => password,
client_id => someclientid
client_secret => somesecret,
username => someuser,
password => somepass,
client_scope => *,
provider => driver-api // Or vendor-api

Надеюсь, это будет вам полезно

person chebaby    schedule 17.10.2018
comment
Большое спасибо за это решение. Но я не мог понять последнюю часть grant_type = ›password, client_id =› someclientid client_secret = ›somesecret, username =› someuser, password = ›somepass, client_scope =› *, provider = ›driver-api // Или vendor-api - person Ahmar Arshad; 17.10.2018
comment
Как мы можем получить токен для вошедшего в систему драйвера или поставщика? - person Ahmar Arshad; 17.10.2018
comment
@AhmarArshad, где вы запрашиваете токены, см. Документы laravel.com/docs/ 5.6 / паспорт # пароль-грант-токен - person chebaby; 17.10.2018
comment
Вместо этого измените папку поставщика, любое решение скорее - person Harat; 21.01.2020
comment
@Harat Что вы думаете о том, чтобы иметь еще одну папку customPassport, создавать необходимые файлы и расширять исходные файлы. Затем в вашем composer.json добавьте часть dont-discover в laravel / паспорт, а затем зарегистрируйте свой собственный CustomPassportServiceProvider в своем app.php - person Edward Chew; 23.08.2020
comment
@EdwardChew отличная идея, но теперь я нашел другое решение, попробуйте laravel sanctum. - person Harat; 24.08.2020
comment
Это дает мне неопределенный метод getEntityByUserCredentials - person sd077; 25.12.2020

Потратив некоторое время, я обнаружил, что в Laravel 7 не требуется никакого специального кода, кроме некоторой конфигурации. Подробнее см. В этом ответе, который я тестировал и реализовал в своих проектах Мульти аутентификация с Laravel 5.4 и паспортом

person Rejoanul Alam    schedule 26.08.2020

Вам не обязательно менять конфигурацию для каждого запроса. На каждого охранника нужен клиент. После создания клиентов, запустив

passport:install

Убедитесь, что вы указали поле провайдера в базе данных. Оно должно быть таким же, как config auth.providers.

После создания клиентов и охранников используйте следующий код при создании токена доступа.

App::clearResolvedInstance(ClientRepository::class);
app()->singleton(ClientRepository::class, function () {
    return new ClientRepository(User::CLIENT_ID, null); // Client id of the model
});

Убедитесь, что вы указали провайдера в таблице oauth_clients.

person Parsa_Gholipour    schedule 23.11.2020