官方文檔:https://docs.golaravel.com/docs/5.5/passport/
Laravel使用Laravel Passport輕松實現(xiàn)API身份驗證,Laravel Passport在幾分鐘內(nèi)就可以為Laravel應(yīng)用程序提供完整的OAuth2服務(wù)器實現(xiàn)
composer安裝
composer require laravel/passport
不過很多時候因為php版本的原因無法安裝,就需要在composer.json--require中添加
"laravel/passport": "4.0.3"
然后
composer update
接下來,將 Passport 的服務(wù)提供者注冊到配置文件 config/app.php 的 providers 數(shù)組中:
Laravel\Passport\PassportServiceProvider::class,
在mysql中創(chuàng)建存儲客戶端和訪問令牌所需的table
php artisan migrate
創(chuàng)建生成安全訪問令牌時所需的加密密鑰,和用于生成訪問令牌的「個人訪問」客戶端和「密碼授權(quán)」客戶端:
php artisan passport:install
建議將生成的令牌令牌寫入.env中,如下
CLIENT_ID=1
CLIENT_SECRET=oSXGS6cu7xAB6gIF05p57itujd2ieyRPatZOsbJl
PASSPORT_CLIENT_ID=2
PASSPORT_CLIENT_SECRET=wYFO2jTAu5IcOHS0pbYTiLrM0M1XmWAPUDYXnOhr
在 Laravel\Passport\HasApiTokens 引入HasApiTokens,用于檢查已認(rèn)證用戶的令牌和使用范圍
<?php
namespace App;
use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use HasApiTokens, Notifiable;
}
接下來,在 AuthServiceProvider 的 boot 方法中調(diào)用 Passport::routes 函數(shù)。這個函數(shù)會注冊發(fā)出訪問令牌并撤銷訪問令牌、客戶端和個人訪問令牌所必需的路由
<?php
namespace App\Providers;
use Laravel\Passport\Passport;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* 應(yīng)用程序的策略映射。
*
* @var array
*/
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Passport::routes();
}
}
最后,將配置文件 config/auth.php 中授權(quán)看守器 guards 的 api 的 driver 選項改為 passport。此調(diào)整會讓你的應(yīng)用程序在在驗證傳入的 API 的請求時使用 Passport 的 TokenGuard 來處理:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
默認(rèn)情況下,Passport 發(fā)放的訪問令牌是永久有效的,不需要刷新。在 AuthServiceProvider 的 boot 方法中配置有效期
use Carbon\Carbon;
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Passport::routes();
Passport::tokensExpireIn(Carbon::now()->addDays(15));
Passport::refreshTokensExpireIn(Carbon::now()->addDays(30));
}
開始使用
登錄后臺代碼,這里使用了guzzlehttp/guzzleHTTP客戶端包
composer require guzzlehttp/guzzle
public function login(){
$email=\request('email');
$password =\request('password');
if (auth()->attempt(['email'=>$email,'password'=>$password])){
$user = User::where('email',$email)->first();
$name = is_null($user) ? '' : $user->name;
return $this->proxy('password',$name,[
'username'=> $email,
'password'=> $password,
'scope'=> '',
]);
}
return response()->json([
'code'=> 501,
'message'=>'賬號密碼錯誤'
]);
}
public function proxy($grantType, $name, array $data = []){
$data = array_merge($data,[
'client_id' => env('PASSPORT_CLIENT_ID'),
'client_secret' => env('PASSPORT_CLIENT_SECRET'),
'grant_type'=>$grantType
]);
$url = 'http://'.$_SERVER["HTTP_HOST"].'/oauth/token';
$http = new GuzzleHttp\Client();
$http->request('POST',$url,[
'verify' => false,
'form_params' => $data
]);
$token = json_decode(( string) $response->getBody(),true);
return response()->json([
'code' => 1,
'data' => [
'token' => $token['access_token'],
'expires_in' => $token['expires_in'],
'user'=>$name
]
])->cookie('refreshToken',$token['refresh_token'],14000,null,null,false,true);
}
登錄成功會返回token,expires_in,user以及存入cookie中的refreshToken
當(dāng)調(diào)用 Passport 保護(hù)下的路由時,接入的 API 應(yīng)用需要將訪問令牌作為 Bearer 令牌放在請求頭 Authorization 中。例如
$response = $client->request('GET', '/api/user', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$accessToken,
],
]);
api.php
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::post('/posts','Auth\PostController@index')->middleware('auth:api');