Можем ли мы использовать паспорт laravel с разными охранниками для аутентификации API для двух разных типов пользователей. Например, у нас есть приложение-драйвер для пользователя-водителя и приложение-поставщик для пользователя-поставщика. У обоих есть разные модели Driver и Vendor. Как мы можем использовать разных охранников для аутентификации обоих типов пользователей с помощью Laravel Passport?
Множественная аутентификация Laravel Passport с использованием гвардейцев
Ответы (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 на правильный класс.
Изменить: теперь в паспорте поддерживается несколько поставщиков услуг защиты. Для получения дополнительной информации перейдите по следующим ссылкам:
Несколько средств защиты аутентификации
Поддержка нескольких охранников
Старый ответ (не рекомендую)
Вот пример 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
Надеюсь, это будет вам полезно
Потратив некоторое время, я обнаружил, что в Laravel 7 не требуется никакого специального кода, кроме некоторой конфигурации. Подробнее см. В этом ответе, который я тестировал и реализовал в своих проектах Мульти аутентификация с Laravel 5.4 и паспортом
Вам не обязательно менять конфигурацию для каждого запроса. На каждого охранника нужен клиент. После создания клиентов, запустив
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.