laravel 5.4以上php
$ composer require laravel/passport
laravel
在配置文件 config/app.php 的providers 數組中註冊 Passport 服務提供者:sql
LaravelPassportPassportServiceProvider::class,數據庫
遷移數據庫 執行完後會生成oauth須要的表json
$ php artisan migrate
api
這一步注意,執行的時候可能會報錯數組
Syntax error or access violation: 1071 Specified key was too long; max key length is 767 byte微信
這是因爲 Laravel5.4默認使用utf8mb4 編碼
utf8 最大長度字符是3字節 utf8mb4是4字節app
解決方法就是composer
數據庫改用utf8mb4
AppServiceProvider.php裏面加上Schema::defaultStringLength(191);
<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\Schema; class AppServiceProvider extends ServiceProvider { /** * Bootstrap any application services. * * @return void */ public function boot() { // Schema::defaultStringLength(191); } /** * Register any application services. * * @return void */ public function register() { // } }
另外Mysql 5.5.3以後才支持utf8mb4也須要注意下
接下來執行
$ php artisan passport:install
會生成兩個客戶端密鑰
Client ID: 1 Client Secret: AwDMcCs65rXkzF80wPaINx5fkoXEfa8lcuuPEvQK Password grant client created successfully. Client ID: 2 Client Secret: KLlLijWk3hX2Ntfzo2iFPgwT4GyITpBjEuDozp5H
這裏能夠配置的只有access token的生命週期默認是永久的
在AuthServiceProvider中配置
use Carbon\Carbon; use Laravel\Passport\Passport; /** * 註冊全部認證/受權服務. * * @return void */ public function boot() { $this->registerPolicies(); Passport::routes(); Passport::tokensExpireIn(Carbon::now()->addDays(15)); Passport::refreshTokensExpireIn(Carbon::now()->addDays(30)); }
修改auth.php
'guards'['driver'] => 'passport'
頒發
應用場景 個人用戶,在別的網站想用個人帳號直接登陸,參考微信登陸。那麼第三方網站就要對接過來,用戶選擇第三方登陸,跳轉到個人頁面,詢問用戶是否容許,用戶容許之後我會帶一個code回去,第三方網站用這個code請求access_token
流程是
請求令牌
'client_id' => 'client-id', 'redirect_uri' => 'http://example.com/callback', 'response_type' => 'code', 'scope' => '',
用戶容許之後拿到code換token
$response = $http->post('http://your-app.com/oauth/token', [ 'form_params' => [ 'grant_type' => 'authorization_code', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'redirect_uri' => 'http://example.com/callback', 'code' => $request->code, ], ]);
token若是過時了,能夠刷新
$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' => '', ], ]);
帳號密碼
這個主要是用於APP(我本身的),用戶經過app輸入帳號和密碼,我用帳號密碼校驗正確了就發送access_token
$response = $http->post('http://your-app.com/oauth/token', [ 'form_params' => [ 'grant_type' => 'password', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'username' => 'taylor@laravel.com', 'password' => 'my-password', 'scope' => '', ], ]);
隱式
這種跟第一種差很少,就是省去了code 直接發放,主要用於
JavaScript 或移動應用中客戶端登陸認證信息不能保存時
客戶端證書
這種主要用於機器之間的通訊
直接用appid 和 appsecret 換令牌
$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', ], ]);
私人訪問令牌
這個用於在程序裏面調用API的時候
好比
$user = App\User::find(1); // 建立一個不帶域的令牌... $token = $user->createToken('Token Name')->accessToken; // 建立一個帶域的令牌... $token = $user->createToken('My Token', ['place-orders'])->accessToken;
在調用api以前須要建立client
建立命令是$ php artisan passport:client
密碼和私人的不一樣其餘都同樣
$ php artisan passport:client --password
$ php artisan passport:client --personal
建立好後得到client-id和client-secret
5.4之後目錄結構發生變化,路由統一寫在routes文件夾下。
API的路由都寫在api.php
肯定好路由就能夠請求接口了
GET 方式 /api/user 'headers' => [ 'Accept' => 'application/json', 'Authorization' => 'Bearer '.$accessToken, ],
寫到這裏遇到一個問題
就是不管怎樣請求 獲取到的token 用來訪問接口的時候 老是返回
Unauthenticated
GOOGLE了下發現好多人也遇到這個問題,聽說是token過時時間的問題
在AuthServiceProvider boot裏面加上
Passport::tokensExpireIn(Carbon::now()->addDays(15)); Passport::refreshTokensExpireIn(Carbon::now()->addDays(30));
這樣應該會解決,然而並無,這裏等之後一時間再研究下(已解決 見下文)
這個問題有了必定進展
目前經過用戶受權頒發令牌的方式經過了
前提是用戶必須登陸,以前返回Unauthenticated 應該是由於用戶未登陸
在應用站跳轉到受權站的時候,此時用戶需登陸狀態,受權之後拿到code再來換access_token 這個方式OK的,能夠正常獲取登陸用戶的信息
帳號密碼獲取令牌的方式也同樣能夠經過
站點以前經過 id 和 secret的方式換token,而後拿token請求接口這種方式目前還不行
坑爹啊,官方文檔沒寫全
經過 client_credentials 方式獲取token,請求接口的時候,路由不能用auth或者scope等中間件去驗證,由於他們會首先驗證有沒有登陸。
咱們須要在app\Http\Kernel.php 的 $routeMiddleware 裏面定義一個客戶端API的中間件
'client_credentials' => \Laravel\Passport\Http\Middleware\CheckClientCredentials::class,
而後在路由裏面Route::middleware('client_credentials')
或者
Route::middleware('client_credentials:做用域名稱')
這樣就能夠實現不登陸直接調用api了
參考文檔