Laravel 使用 Guards 的 Passport 多重身份验证
Laravel Passport Multiple Authentication using Guards
我们能否使用 laravel 具有不同保护措施的护照来为两种不同类型的用户验证 API。
例如,我们为 driver 用户提供 driver 应用,为供应商用户提供供应商应用。两者都有不同的模型 Driver 和供应商。
我们如何使用不同的守卫来验证使用 Laravel Passport 的两种类型的用户?
编辑:Passport 现在支持多个守卫用户提供商。请参考以下链接了解更多信息:
Multiple Authentication Guards
旧答案(不推荐)
这里有一个 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\passport\src\Bridge\UserRepository.php
Copy/Paste 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
);
完成此操作后,您将能够将额外的 key/value 对传递给您的访问令牌请求,例如:
grant_type => password,
client_id => someclientid
client_secret => somesecret,
username => someuser,
password => somepass,
client_scope => *,
provider => driver-api // Or vendor-api
希望对您有所帮助
我设法通过使用一个简单的中间件创建了多个身份验证(laravel/passport)。
第 1 步:config/auth.php
将您的用户class添加到提供商
'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中新建的中间件,更新hand方法如下
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,
...
];
第四步:给路由添加中间件
Route::group(['middleware' => ['auth.admin','auth:api']], function() {
第 5 步:登录控制器(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 身份验证提供程序更改为正确的 class。
经过一段时间后我发现在Laravel 7中除了一些配置外不需要自定义代码。有关详细信息,请查看我已经在我的项目中测试和实施的答案
Multi Auth with Laravel 5.4 and Passport
您不一定需要为每个请求更改配置。
每个守卫都需要一个客户。通过 运行
创建客户后
passport:install
确保您在数据库中指定了提供商字段。它应该与 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 table 中指定了提供商。
我们能否使用 laravel 具有不同保护措施的护照来为两种不同类型的用户验证 API。 例如,我们为 driver 用户提供 driver 应用,为供应商用户提供供应商应用。两者都有不同的模型 Driver 和供应商。 我们如何使用不同的守卫来验证使用 Laravel Passport 的两种类型的用户?
编辑:Passport 现在支持多个守卫用户提供商。请参考以下链接了解更多信息:
Multiple Authentication Guards
旧答案(不推荐)
这里有一个 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\passport\src\Bridge\UserRepository.php
Copy/Paste 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
);
完成此操作后,您将能够将额外的 key/value 对传递给您的访问令牌请求,例如:
grant_type => password,
client_id => someclientid
client_secret => somesecret,
username => someuser,
password => somepass,
client_scope => *,
provider => driver-api // Or vendor-api
希望对您有所帮助
我设法通过使用一个简单的中间件创建了多个身份验证(laravel/passport)。
第 1 步:config/auth.php
将您的用户class添加到提供商
'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中新建的中间件,更新hand方法如下
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,
...
];
第四步:给路由添加中间件
Route::group(['middleware' => ['auth.admin','auth:api']], function() {
第 5 步:登录控制器(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 身份验证提供程序更改为正确的 class。
经过一段时间后我发现在Laravel 7中除了一些配置外不需要自定义代码。有关详细信息,请查看我已经在我的项目中测试和实施的答案 Multi Auth with Laravel 5.4 and Passport
您不一定需要为每个请求更改配置。 每个守卫都需要一个客户。通过 运行
创建客户后passport:install
确保您在数据库中指定了提供商字段。它应该与 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 table 中指定了提供商。