Passport OAuth 認證 解析

Sinker發表於2019-07-18

本示例在laravel 5.5.*版本下

一. 安裝

composer require paragonie/random_compat=~2.0
composer require laravel/passport=~4.0

將 Passport 的服務提供者註冊到配置檔案 config/app.php 的 providers 陣列中:

Laravel\Passport\PassportServiceProvider::class,

Passport 使用服務提供者註冊內部的資料庫遷移指令碼目錄,所以上一步完成後,你需要更新你的資料庫結構。Passport 的遷移指令碼會自動建立應用程式需要的客戶端資料表和令牌資料表:

php artisan migrate

接下來,你需要執行 passport:install 命令來建立生成安全訪問令牌時用到的加密金鑰,同時,這條命令也會建立「私人訪問」客戶端和「密碼授權」客戶端:

都需要進行安裝
php artisan passport:install
將 Laravel\Passport\HasApiTokens Trait 新增到 App\User 模型中
User模型是框架自帶的
namespace  App; 
use  Laravel\Passport\HasApiTokens;  
use  Illuminate\Notifications\Notifiable; 
use  Illuminate\Foundation\Auth\User  as Authenticatable;  
class  User  extends  Authenticatable 
{  
    use  HasApiTokens, Notifiable; 
}

要在 Providers/AuthServiceProviderboot 方法中呼叫 Passport::routes 函式。這個函式會註冊一些在訪問令牌、客戶端、私人訪問令牌的發放和吊銷過程中會用到的必要路由

 public function boot()
    {
        $this->registerPolicies();
        Passport::routes();
    }

需要將配置檔案 config/auth.phpapi 部分的授權保護項( driver )改為 passport 。此調整會讓你的應用程式在接收到 API 的授權請求時使用 Passport 的 TokenGuard 來處理:

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],

預設情況下,Passport 發放的訪問令牌是永久有效的,不需要重新整理。但是如果你想給訪問令牌配置一個短一些的有效期,那你就需要用到 tokensExpireInrefreshTokensExpireIn 方法了,上述兩個方法同樣需要在 Providers/AuthServiceProviderboot 方法中呼叫:

public function boot()
{
    $this->registerPolicies();
    Passport::routes();
    Passport::tokensExpireIn(Carbon::now()->addDays(15)); #時 分
    Passport::refreshTokensExpireIn(Carbon::now()->addDays(30));#時 分
}

二. 密碼授權令牌

OAuth2 密碼授權機制可以讓自有應用基於郵箱地址(使用者名稱)和密碼獲取訪問令牌,自有應用比如你的手機客戶端。這樣就允許自由應用無需跳轉步驟即可透過整個 OAuth2 的授權過程。
如果想要透過密碼授權機制來發布令牌,首先你需要建立一個密碼授權客戶端。

php artisan passport:client --password

也可以使用postman請求

$http = new GuzzleHttp\Client;
$response = $http->post('http://your-app.com/oauth/token', [
    'form_params' => [
        'grant_type' => 'password',
        'client_id' => 'client-id',                  透過  php artisan passport:client --password  輸入在user表建立的郵箱  就可以生成id和金鑰
        'client_secret' => 'client-secret',
        'username' => 'taylor@laravel.com',
        'password' => 'my-password',
        'scope' => '',
    ],
]);
return json_decode((string) $response->getBody(), true);

返回資料

{
    "token_type": "Bearer",
    "expires_in": 54000,
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6Ijc5NzI1ZmMzMWM1YWEyNDZmOWFiYjdiODMwNWY0Y2IyODEzZDQ2YjY4YWJhNTJmMGNkZWM3ODA4ZDI5ZTZiYWFlOGY0N2U4ZDFmNzQzYmNhIn0.eyJhdWQiOiI0IiwianRpIjoiNzk3MjVmYzMxYzVhYTI0NmY5YWJiN2I4MzA1ZjRjYjI4MTNkNDZiNjhhYmE1MmYwY2RlYzc4MDhkMjllNmJhYWU4ZjQ3ZThkMWY3NDNiY2EiLCJpYXQiOjE1NjM0MzAwNTIsIm5iZiI6MTU2MzQzMDA1MiwiZXhwIjoxNTYzNDg0MDUyLCJzdWIiOiIyIiwic2NvcGVzIjpbXX0.2Pn-HITcb6zqg0X4u0lpz4aN8JBZnX9LdTwAW_10UOFxyKzpOpPwtCdBK9xB5CBIftfHHqOm1wsff_6-c9rgi1mnpVdb1ozcZNNoR764hPgiBQ7N5yc4hQMrq3CwUt8IYtZsjo1GWm_O4B6i7oKXiWRyTwok5yBKXbK52jQNxCWkxUAkQMOzI5iEQjok6K-xL1XeInkXK4a5a7_tCCTbp0_EzRCeohobDISG0WslyUbRFNA3LElyJa_vL7aX0Ro_2tC7R9EvFmz23GOn0mPwnsXu2tasFHEhAxXyXiM0U28AHItp34ZNlMKQ7y7QHHHfyyR1GiFr3MeODJOkbZx6FuAp8Wk0BWSCa2REi8-cn1QbdKR1abAZKa7HgLlQxN8vYU4QdIth8AS-XP97tdy-jGTcp6MFJ0zzmrudq2WgJOfKSoVMmUjg6_xFUqqdyD4HeAztqJG5qm2POYAWOlnrH1we2C5CCkGfqlwFljXrPaCB9l10yJkRxd7Y_bOjD297cVTzH0LnvTA74U-otqE_tSRjjlWWdMf5iG1qQT-l8gc8BdcLigCyBWM3eU1XNTqbYVBbLIu1LUh2LrI-XQGjTTTB43OU5pKAnwVsEKPqEKXaUIwf6WuQvI-Eh1i7uvLsl-Yg_3M3Z8MeIFfxx-BRAQw7m9VM4FWmNCZBFSWmJTw",
    "refresh_token": "def50200684d443678ee8b18eccc0130715234520466e17fb47e8eabbb7a3ebaf0dc94ac79cd9213fe3d06934b97486a2f3c93e88fed034b983b52dc3614d0aca8d1ccca8671320f68b156c5b8791d273224dbda52a86a271aa96dcdc166245ddbf8838109bd780c8f60f064443f3abd0210cf825a9c0f741c047498dbf683760a0a17b312f6f9252193757dfd6d3849ed200d920ee8f71a433f1a50060464a0ef11e5082b7337bd45f4b685210e42b370364e9e13e2b19cc39d092356096841f55c2264744094a8022716c899b62ce0db3c856963a062626385d9d0a93809e9bc2aac84e8c6cd773566f4b9b05352f6a0aa467713c8ee41a4d1e69b55e76d35bed93c5bd0ee591982460994ab721a07aec155a3016f1626321ff7783567b9df1aac6e78883384afb14a7fffaf1ab7149bb96c88e8702e7b06be6f160523dd7c2a3ec2974b10af72038f74e433d6208a3873ebe2810aa95743a13a1a13efd83be4"
}

重新整理令牌

$http = new GuzzleHttp\Client;
$response = $http->post('http://your-app.com/oauth/token', [
    'form_params' => [
        'grant_type' => 'refresh_token',
        'refresh_token' => 'the-refresh-token',    #發放令牌的時候會一起返回
        'client_id' => 'client-id',
        'client_secret' => 'client-secret',
        'scope' => '',
    ],
]);
return json_decode((string) $response->getBody(), true);

保護機制

由於在config/auth.php    將api的驅動改成了passport
'guards' => [
  'web' => [
  'driver' => 'session',
  'provider' => 'users',
  ],
  'api' => [
  'driver' => 'passport',
  'provider' => 'users',
  ],
],
所以在Http/Kernel.php種  
  'api' => [
//            'throttle:60,1',\
//            'bindings',\
  'auth:api'
  ],

客戶端授權令牌

php artisan passport:client
接下來,要使用這種授權,你首先需要在 `app/Http/Kernel.php``$routeMiddleware` 變數中新增新的中介軟體:

use Laravel\Passport\Http\Middleware\CheckClientCredentials;

protected $routeMiddleware = [
‘client’ => CheckClientCredentials::class,
];

獲取令牌

$guzzle = new GuzzleHttp\Client;

$response = $guzzle->post('http://your-app.com/oauth/token', [
    'form_params' => [
        'grant_type' => 'client_credentials',
        'client_id' => 'client-id',
        'client_secret' => 'client-secret',
        'scope' => 'your-scope',
    ],
]);
return json_decode((string) $response->getBody(), true)['access_token'];

請求介面的時候

$response = $client->request('GET', '/api/user', [
    'headers' => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer '.$accessToken,  #$accessToken 是獲取返回的accesstoken
    ],
]);

php artisan passport:keys 生成兩個檔案 oauth-private.key oauth-public.key

結語

詳細解說:Passport OAuth 認證

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章