smartins / 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 Password 自 9.0 版本起已提供原生实现,因此该包已过时,具体信息请见 版本 9.0
Laravel Passport Multi-Auth
为 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 Package Discovery 中删除 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 数组中添加一个新的 guard
,使用驱动程序 passport
和上面添加的提供者
// ... 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], // ** New guard ** 'admin' => [ 'driver' => 'passport', 'provider' => 'admins', ], ], // ...
在 app/Http/Kernel.php
文件中将中间件 AddCustomProvider
注册到 $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
是必需的,用于包裹在 AddCustomProvider
中间件中的路由。您必须传递在 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 路由的访问令牌,使用已注册的中间件。此中间件将添加能力到 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
guard 的用法与 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
中使用默认 guard web
。例如
'defaults' => [ 'guard' => 'web', ],
存在一个已打开的 问题,将尽快进行分析。
单元测试
而不是使用 Laravel\Passport\Passport::actingAs()
方法,请使用 SMartins\PassportMultiauth\PassportMultiauth::actingAs()
。区别在于此包的 actingAs
根据第一个参数传递的 Authenticatable
实例获取 guard 并使用您的 guard 认证此用户。在认证请求(使用包中的 auth
中间件 - SMartins\PassportMultiauth\Http\Middleware\MultiAuthenticate)
中,将在 Request
上检查 guard 以返回用户或抛出 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 项目中看到一个完整的 Passport-Multiauth
实现,使用 Password Grant Tokens
和 Personal Access Token
。
贡献者
基于 renanwilian 对 Passport Multi-Auth 问题 的回复。