【问题标题】:Laravel Passport - Allow either auth:api OR client_creds in route groupLaravel Passport - 在路由组中允许 auth:api 或 client_creds
【发布时间】:2018-11-23 01:41:50
【问题描述】:
我希望可以使用标准的 auth:api 中间件或通过 CheckClientCredentials 中间件访问一组路由。
我看不出这怎么可能,因为无法将中间件设置为只需要列出的中间件之一。
是否有 Passport 中间件允许我不知道的任何类型的 API 身份验证?
或者有没有一种干净的方法来创建一个自定义中间件来测试其中一个中间件?
【问题讨论】:
标签:
laravel
laravel-passport
laravel-middleware
【解决方案1】:
我最终将所有需要身份验证的路由存储在一个名为api-authenticated.php 的单独路由文件中。在 RouteServiceProvider.php 中,我根据 Authorization 标头的存在有条件地为这些路由应用 web 和 api 中间件组。设置 Authorization 标头后,您就知道用户是 API 客户端。
在Providers/RouteServiceProvider.php:
/**
* Define the "api" routes for the application.
*
* These routes are typically stateless.
*
* @return void
*/
protected function mapApiRoutes()
{
Route::prefix('api')
->middleware('api')
->namespace($this->apiNamespace)
->name('api.')
->group(__DIR__ . '/../../routes/api.php');
}
/**
* Define the authenticated "api" routes for the application.
*
* These routes are typically stateless, but are also used in
* a stateful context as the first-party uses cookies for
* authenticaton
*
* @return void
*/
public function mapAuthenticatedApiRoutes()
{
$stateless = request()->hasHeader('Authorization');
Route::prefix('api')
->middleware($stateless ? ['api', 'auth:api'] : ['web', 'auth'])
->namespace($this->apiNamespace)
->name('api.')
->group(__DIR__ . '/../../routes/api-authenticated.php');
}
【解决方案2】:
我接受了 Joshua 关于 similar answer here 的建议,并创建了一个包含两个 auth 中间件的新中间件。
为其他遇到此问题的其他人提供工作中间件类。这将首先尝试 Auth 保护中间件,如果无法验证请求,它将尝试使用 Client Credentials Passport 中间件进行身份验证。
namespace App\Http\Middleware;
use Closure;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Auth\Middleware\Authenticate as AuthGuardMiddleware;
use Laravel\Passport\Http\Middleware\CheckClientCredentials as ClientCredMiddleware;
class AuthenticateWithApiOrClientCreds
{
/**
* Authenticate a request with either Authenticate OR CheckClientCredentials Middleware
*
* @param $request
* @param Closure $next
* @param mixed ...$scopes
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function handle($request, Closure $next, ...$scopes)
{
$auth_guard_middleware = app()->make(AuthGuardMiddleware::class);
try {
$response = $auth_guard_middleware->handle($request, $next, 'api');
} catch (AuthenticationException $e) {
$client_cred_middleware = app()->make(ClientCredMiddleware::class);
$response = $client_cred_middleware->handle($request, $next, ...$scopes);
}
return $response;
}
}
【解决方案3】:
Laravel 不提供 OR 中间件。虽然有几种解决方法,就像之前问过的here。
如果您正在寻找更改api.php 默认中间件(默认为auth:api)的方法,您可以在目录:app\Providers\RouteServiceProvider.php 中查看它,函数名称为:mapApiRoutes()。