leandrodiogenes / passport-multiauth
为Laravel Passport添加多认证支持
Requires
- php: ^7.2
- laravel/passport: ^8.0
Requires (Dev)
- mockery/mockery: ^1.0
- orchestra/database: ^4.0
- orchestra/testbench: ^4.0
README
为Laravel Passport添加多认证支持
从4.0升级到5.0
- 要从版本4.0升级到5.0,请遵循此指南
从2.0升级到3.0
- 要从版本2.0升级到3.0,请遵循此指南
从1.0升级到2.0
- 要从版本1.0升级到2.0,请遵循此指南
兼容性
安装和配置
使用composer安装
$ composer require smartins/passport-multiauth
为了确保一切正常工作,我们需要确保在注册Laravel\Passport\PassportServiceProvider::class
服务提供者之前,先注册SMartins\PassportMultiauth\Providers\MultiauthServiceProvider::class
服务提供者。
首先,您需要从Laravel 包发现中删除laravel/passport
包。
在您的composer.json
文件中,将laravel/passport
添加到extra.laravel.dont-discover
数组中
"extra": { "laravel": { "dont-discover": [ "laravel/passport" ] } },
并在config/app.php
上手动注册提供者
'providers' => [ // ... SMartins\PassportMultiauth\Providers\MultiauthServiceProvider::class, Laravel\Passport\PassportServiceProvider::class, ],
警告:提供者SMartins\PassportMultiauth\Providers\MultiauthServiceProvider::class
必须添加到Laravel\Passport\PassportServiceProvider::class
之前才能正常工作。
可能需要清除引导缓存文件以重新注册提供者
php artisan optimize:clear
迁移数据库以创建oauth_access_token_providers
表
$ php artisan migrate
注意:如果您没有运行安装Passport的命令,则运行
$ php artisan passport:install
与Laravel Passport核心中的Laravel\Passport\HasApiTokens
特性相比,使用特性SMartins\PassportMultiauth\HasMultiAuthApiTokens
。
内部,这个HasMultiAuthApiTokens
使用了HasApiTokens
,并重写了方法tokens()
和createToken($name, $scopes = [])
。方法tokens()
的行为已更改为与表oauth_access_token_providers
连接,仅获取为特定模型创建的令牌。方法createToken($name, $scopes = [])
已更改为使用在config/auth.php
中定义的provider
创建令牌。现在,当您创建令牌时,此令牌将与调用该模型的模型相关联。
在config/auth.php
中使用继承自Authenticatable
类的模型添加新的提供者,并使用HasMultiAuthApiTokens
特性。
示例
配置您的模型
use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; use SMartins\PassportMultiauth\HasMultiAuthApiTokens; class Admin extends Authenticatable { use Notifiable, HasMultiAuthApiTokens; }
以及您的config/auth.php
提供者
// ... 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], // ** New provider** 'admins' => [ 'driver' => 'eloquent', 'model' => App\Admin::class, ], ], // ...
在config/auth.php
的guards数组中使用驱动passport
和上面添加的提供者添加新的guard
// ... 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], // ** New guard ** 'admin' => [ 'driver' => 'passport', 'provider' => 'admins', ], ], // ...
将中间件AddCustomProvider
注册到app/Http/Kernel.php
文件上的$routeMiddleware
属性。
class Kernel extends HttpKernel { // ... /** * The application's route middleware. * * These middleware may be assigned to groups or used individually. * * @var array */ protected $routeMiddleware = [ // ... 'oauth.providers' => \SMartins\PassportMultiauth\Http\Middleware\AddCustomProvider::class, ]; // ... }
注意:中间件AddCustomProvider
的provider
参数是必需的。您必须传递在config/auth.php
上配置的有效提供者。
在app/Http/Kernel
的$routeMiddleware
属性上添加新的中间件Authenticate
。
class Kernel extends HttpKernel { // ... /** * The application's route middleware. * * These middleware may be assigned to groups or used individually. * * @var array */ protected $routeMiddleware = [ 'auth' => \Illuminate\Auth\Middleware\Authenticate::class, // ** New middleware ** 'multiauth' => \SMartins\PassportMultiauth\Http\Middleware\MultiAuthenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, 'can' => \Illuminate\Auth\Middleware\Authorize::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'oauth.providers' => \SMartins\PassportMultiauth\Http\Middleware\AddCustomProvider::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, ]; // ... }
在AuthServiceProvider
中封装通行证路由的访问令牌,以使用已注册的中间件。此中间件将为Passport
路由oauth/token
添加使用请求中provider
参数的能力
namespace App\Providers; use Route; use Laravel\Passport\Passport; use Illuminate\Support\Facades\Gate; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; class AuthServiceProvider extends ServiceProvider { // ... /** * Register any authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); Passport::routes(); // Middleware `oauth.providers` middleware defined on $routeMiddleware above Route::group(['middleware' => 'oauth.providers'], function () { Passport::routes(function ($router) { return $router->forAccessTokens(); }); }); } // ... }
可选:发布迁移
只需运行带有包提供者的vendor:publish
artisan命令即可
$ php artisan vendor:publish --provider="SMartins\PassportMultiauth\Providers\MultiauthServiceProvider"
如果您不打算使用 PassportMultiauth 的默认迁移,应在您的 AppServiceProvider 的 register 方法中调用 SMartins\PassportMultiauth\PassportMultiauth::ignoreMigrations
方法。
用法
在 /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" }
您可以根据需要将 guards 传递给 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
的用法相同。
您可以将多个 guards 传递给 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(); }); });
您也可以使用 Auth
门面
Auth::check(); Auth::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" }
使用作用域
只需使用来自 Laravel\Passport
的 scope
和 scopes
中间件。
protected $routeMiddleware = [ 'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class, 'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class, ];
个人访问令牌
在您的模型中,如果使用了 SMartins\PassportMultiauth\HasMultiAuthApiTokens
特性,您可以使用 createToken($name, $scopes = [])
和 tokens()
方法来管理您的个人访问令牌。例如
$user = User::find(1); $admin = Admin::find(1); // Create token from Model instance. $user->createToken('My Token'); $admin->createToken('My Admin Token'); // Get the tokens created to this user. $user->tokens()->each(function ($token) { echo $token->name; // My Token }); $admin->tokens()->each(function ($token) { echo $token->name; // My Admin Token });
已知问题
为了正确工作,您必须在 config/auth.php
中使用默认的守卫 web
。例如
'defaults' => [ 'guard' => 'web', ],
存在一个已开放的 问题,我们将尽快分析。
单元测试
不要使用 Laravel\Passport\Passport::actingAs()
方法,而应使用 SMartins\PassportMultiauth\PassportMultiauth::actingAs()
。区别在于此包中的 actingAs
会根据第一个参数传递的 Authenticatable
实例获取守卫,并使用您的守卫来验证此用户。在经过验证的请求(使用包中的 auth
中间件 - SMartins\PassportMultiauth\Http\Middleware\MultiAuthenticate)
)中,会在 Request
中检查守卫,以返回用户或抛出 Unauthenticated
异常。例如
use App\User; use Tests\TestCase; use SMartins\PassportMultiauth\PassportMultiauth; class AuthTest extends TestCase { public function fooTest() { $user = factory(User::class)->create(); PassportMultiauth::actingAs($user); $this->json('GET', 'api/user'); } public function withScopesTest() { $user = factory(User::class)->create(); PassportMultiauth::actingAs($user, ['see-balance']); $this->json('GET', 'api/balance'); } }
示例项目
您可以在 passport-multiauth-demo 项目中看到使用 Password Grant Tokens
和 Personal Access Token
的完整 Passport-Multiauth
实现。
贡献者
基于 renanwilian 对 Passport Multi-Auth 问题 的回复。