aaranda/lumen-passport-multiauth

Lumen版本的Laravel Passport和多认证

dev-main 2021-04-02 21:43 UTC

This package is auto-updated.

Last update: 2024-09-29 05:43:10 UTC


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"
}

贡献者

基于renanwilian的 lumen-passport