Laravel Passport - 在路由组中允许 auth:api 或 client_creds

Laravel Passport - Allow either auth:api OR client_creds in route group

我希望可以使用标准 auth:api 中间件或 CheckClientCredentials 中间件访问一组路由。

我看不出这怎么可能,因为无法将中间件设置为只需要列出的中间件之一。

是否有 Passport 中间件允许我不知道的任何类型的 API 身份验证?

或者是否有一种干净的方法来创建自定义中间件来测试其中一个中间件?

Laravel 不提供 OR 中间件。尽管有几个解决方法,就像之前被问到的那样 .

如果您正在寻找更改 api.php 默认中间件(默认为 auth:api)的方法,您可以在目录中看到它:app\Providers\RouteServiceProvider.php 函数名称:mapApiRoutes().

我采纳了 Joshua 关于 的建议,并创建了一个包含两个身份验证中间件的新中间件。

Working Middleware class 对于遇到下面这个问题的其他人。这将首先尝试 Auth guard 中间件,如果无法对请求进行身份验证,它将尝试使用 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;
    }
}

我最终将所有需要身份验证的路由存储在一个名为 api-authenticated.php 的单独路由文件中。在 RouteServiceProvider.php 中,我根据授权 header 的存在有条件地为这些路由应用 webapi 中间件组。设置授权 header 后,您知道用户是 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');
}