前段時間(大概一年之前)寫了個項目使用了先後端代碼分離的架構,同時又由於業務須要出現了管理端和前臺商戶端兩套用戶表登錄的需求。php
由於使用了 passport 包作登錄認證,可是passport又不支持多用戶系統認證。因此那時候使用了一箇中間表的方式去作認證,這種方式能夠解決問題,可是太過複雜。laravel
最近有個新的項目,又遇到了一樣的問題因此網上找了一下是否有簡單的解決方案,果真找到了一個輪子用sfelix-martins/passport-multiauth,使用它能夠簡單的實現,先後臺分離架構下使用 passport 進行先後端用戶各自的認證。git
這裏要感謝下 Samuel Martins 爲咱們提供了這麼優秀的輪子,目前已經更新到3.0版本。github
具體的使用方法,其實看文檔基本已經很簡單了。不過這裏仍是簡單的寫一下我使用的過程。web
在此以前,你須要看過使用 passport 的相關教程json
1.引入 smartins/passport-multiauth後端
composer require smartins/passport-multiauth
2.遷移數據表 oauth_access_token_providersapi
php artisan migrate
3.在須要認證的模型內引入 HasMultiAuthApiTokens數組
use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; use SMartins\PassportMultiauth\HasMultiAuthApiTokens; class Admin extends Authenticatable { use Notifiable, HasMultiAuthApiTokens; }
4.在 config/auth.php providers 數組內增長對應的 providersession
// ... 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], // ** New provider** 'admins' => [ 'driver' => 'eloquent', 'model' => App\Admin::class, ], ],
5.在 config/auth.php guards 數組內增長對應的 guard
// ... 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], // ** New guard ** 'admin' => [ 'driver' => 'passport', 'provider' => 'admins', ], ], // ...
5.在 app/Http/Kernel.php 的 $routeMiddleware 數組內增長 AddCustomProvider 中間件。
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, 'auth' => \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, ]; // ... }
6.在 AuthServiceProvider 裏面增長對應的路由
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(); }); }); } // ... }
7.運行 vendor:publish
php artisan vendor:publish --provider="SMartins\PassportMultiauth\Providers\MultiauthServiceProvider"
8.在使用 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" }
到此基本就能夠進行多表的認證了。
在使用過程當中遇到過一個小問題,由於我是先使用 passport ,在開發過程當中爲了方便直接把對應的 oauth_client 表是直接用 seeder 填充的,這也樣就省去了每次重置數據表的時候還須要再次運行 passport:install 去生成數據。當我使用 Personal Access Tokens 的時候會報一個錯誤
Trying to get property 'client' of non-boject at >>>\\vendor\laravel\\passport\\src\\ClientRepository.php:81
這個問題是由於 oauth_personal_access_clients 表裏面沒有數據,增長一條 oauth_personal_access_client 的數據就能夠了