aaranda / lumen-passport-multiauth
Lumen版本的Laravel Passport和多认证
dev-main
2021-04-02 21:43 UTC
Requires
- php: >=7.3
- laravel/passport: ^10.1.0
README
将护照和多认证支持添加到Lumen
兼容性
安装
使用Composer安装
$ composer require aaranda/lumen-passport-multiauth:^0.1
配置
首先,您需要发布您的Lumen配置文件夹
cp -a vendor/laravel/lumen-framework/config config
以便您可以添加您想要使用的新的提供者和守卫。
您需要在您的bootstrap/app.php文件中取消注释并添加一些行
//uncomment $app->withFacades(); //uncomment $app->withEloquent(); //add in the config file section $app->configure('auth'); //Uncomment your route middleware and add the next lines $app->routeMiddleware([ 'auth' => App\Http\Middleware\Authenticate::class, 'client' => App\Http\Middleware\CheckClientCredentials::class, 'throttle' => Aaranda\LumenPassportMultiauth\Http\Middleware\ThrottleRequests::class, 'oauth.providers' => Aaranda\LumenPassportMultiauth\Http\Middleware\AddCustomProvider::class, 'multiauth' => Aaranda\LumenPassportMultiauth\Http\Middleware\MultiAuthenticate::class, //if you are going to use scopes, you can add the next route middlewares 'scopes' => Laravel\Passport\Http\Middleware\CheckScopes::class, 'scope' => Laravel\Passport\Http\Middleware\CheckForAnyScope::class, ]); //and register the next service providers in this same order $app->register(App\Providers\AuthServiceProvider::class); $app->register(Aaranda\LumenPassportMultiauth\Providers\MultiauthServiceProvider::class); $app->register(Laravel\Passport\PassportServiceProvider::class);
在app/Providers/AuthServiceProvider.php中的AuthServiceProvider中封装并注册护照路由的访问令牌,使用注册的中间件。此中间件将使Passport
路由oauth/token
能够使用请求中的provider
参数的值
namespace App\Providers; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Gate; use Illuminate\Support\ServiceProvider; use Aaranda\LumenPassportMultiauth\Passport; use Illuminate\Support\Facades\Route; class AuthServiceProvider extends ServiceProvider { /** * Register any application services. * * @return void */ public function register() { // } /** * Boot the authentication services for the application. * * @return void */ public function boot() { Route::group(['middleware' => 'oauth.providers'], function () { Passport::routes(function ($router) { return $router->forAccessTokens(); }); }); // change the default token expiration Passport::tokensExpireIn(Carbon::now()->addDays(15)); // change the default refresh token expiration Passport::refreshTokensExpireIn(Carbon::now()->addDays(30)); } }
在您的App\Http\Middleware文件夹中创建一个CheckClientCredentials.php文件
namespace App\Http\Middleware; use Illuminate\Auth\AuthenticationException; use Laravel\Passport\Exceptions\MissingScopeException; class CheckClientCredentials extends CheckCredentials { /** * Validate token credentials. * * @param \Laravel\Passport\Token $token * @return void * * @throws \Illuminate\Auth\AuthenticationException */ protected function validateCredentials($token) { if (! $token) { return response('Unauthorized.', 401); } } /** * Validate token credentials. * * @param \Laravel\Passport\Token $token * @param array $scopes * @return void * * @throws \Laravel\Passport\Exceptions\MissingScopeException */ protected function validateScopes($token, $scopes) { if (in_array('*', $token->scopes)) { return; } foreach ($scopes as $scope) { if ($token->cant($scope)) { throw new MissingScopeException($scope); } } } }
和一个CheckCredentials.php文件
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Auth\AuthenticationException; use Laravel\Passport\TokenRepository; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Nyholm\Psr7\Factory\Psr17Factory; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; abstract class CheckCredentials { /** * The Resource Server instance. * * @var \League\OAuth2\Server\ResourceServer */ protected $server; /** * Token Repository. * * @var \Laravel\Passport\TokenRepository */ protected $repository; /** * Create a new middleware instance. * * @param \League\OAuth2\Server\ResourceServer $server * @param \Laravel\Passport\TokenRepository $repository * @return void */ public function __construct(ResourceServer $server, TokenRepository $repository) { $this->server = $server; $this->repository = $repository; } /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param mixed ...$scopes * @return mixed * * @throws \Illuminate\Auth\AuthenticationException */ public function handle($request, Closure $next, ...$scopes) { $psr = (new PsrHttpFactory( new Psr17Factory, new Psr17Factory, new Psr17Factory, new Psr17Factory ))->createRequest($request); try { $psr = $this->server->validateAuthenticatedRequest($psr); } catch (OAuthServerException $e) { return response('Unauthorized.', 401); } $this->validate($psr, $scopes); return $next($request); } /** * Validate the scopes and token on the incoming request. * * @param \Psr\Http\Message\ServerRequestInterface $psr * @param array $scopes * @return void * * @throws \Laravel\Passport\Exceptions\MissingScopeException|\Illuminate\Auth\AuthenticationException */ protected function validate($psr, $scopes) { $token = $this->repository->find($psr->getAttribute('oauth_access_token_id')); $this->validateCredentials($token); $this->validateScopes($token, $scopes); } /** * Validate token credentials. * * @param \Laravel\Passport\Token $token * @return void * * @throws \Illuminate\Auth\AuthenticationException */ abstract protected function validateCredentials($token); /** * Validate token scopes. * * @param \Laravel\Passport\Token $token * @param array $scopes * @return void * * @throws \Laravel\Passport\Exceptions\MissingScopeException */ abstract protected function validateScopes($token, $scopes); }
现在,您需要将必要的类添加到您将要使用的提供者的模型中。例如,如果您将使用一个User模型和一个Admin模型,那么您需要声明它们如下
namespace App; use Aaranda\LumenPassportMultiauth\HasMultiAuthApiTokens; use Illuminate\Auth\Authenticatable; use Laravel\Lumen\Auth\Authorizable; use Illuminate\Database\Eloquent\Model; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; class User extends Model implements AuthenticatableContract, AuthorizableContract { use HasMultiAuthApiTokens, Authenticatable, Authorizable; // rest of the model }
和
namespace App; use Aaranda\LumenPassportMultiauth\HasMultiAuthApiTokens; use Illuminate\Auth\Authenticatable; use Laravel\Lumen\Auth\Authorizable; use Illuminate\Database\Eloquent\Model; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; class Admin extends Model implements AuthenticatableContract, AuthorizableContract { use HasMultiAuthApiTokens, Authenticatable, Authorizable; // rest of the model }
现在您已经完成了所有必要的步骤,在您最近发布的配置文件夹中
您可以在config/auth.php文件中添加您的新自定义提供者和守卫
'providers' => [ //user provider 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class, ], // admin provider 'admins' => [ 'driver' => 'eloquent', 'model' => App\Models\Admin::class, ], ], 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], //user guard 'users' => [ 'driver' => 'passport', 'provider' => 'users', ], //admin guard 'admin' => [ 'driver' => 'passport', 'provider' => 'admins', ], ],
最后,您需要迁移护照表
php artisan migrate
以及Passport所需的其它必要东西,如密钥注释
php artisan passport:install
使用
在/oauth/token
请求中添加provider
参数
POST /oauth/token HTTP/1.1 Host: localhost Accept: application/json, text/plain, */* Content-Type: application/json;charset=UTF-8 Cache-Control: no-cache { "username":"user@domain.com", "password":"password", "grant_type" : "password", "client_id": "client-id", "client_secret" : "client-secret", "provider" : "admins" }
您可以在multiauth
中间件中按需传递您的守卫。例如
Route::group(['middleware' => ['api', 'multiauth:admin']], function () { Route::get('/admin', function ($request) { // Get the logged admin instance return $request->user(); // You can use too `$request->user('admin')` passing the guard. }); });
使用api
守卫与使用admin
的示例相同。
您可以将多个守卫传递给multiauth
中间件。
Route::group(['middleware' => ['api', 'multiauth:admin,api']], function () { Route::get('/admin', function ($request) { // The instance of user authenticated (Admin or User in this case) will be returned return $request->user(); }); });
刷新令牌
在/oauth/token
请求中添加provider
参数
POST /oauth/token HTTP/1.1 Host: localhost Accept: application/json, text/plain, */* Content-Type: application/json;charset=UTF-8 Cache-Control: no-cache { "grant_type" : "refresh_token", "client_id": "client-id", "client_secret" : "client-secret", "refresh_token" : "refresh-token", "provider" : "admins" }