使用 postman 除錯 jwt 開發的介面
我的github部落格:zgxxx.github.io/
上一篇部落格文章 ofollow,noindex">juejin.im/post/5be447… 介紹了laravel使用dingo+jwt開發API的幾個步驟,那麼在實際操作中,我們需要測試API
$api = app('Dingo\Api\Routing\Router'); $api->version('v1', ['namespace' => 'App\Http\Controllers\V1'], function ($api) { $api->post('register', 'AuthController@register'); $api->post('login', 'AuthController@login'); $api->post('logout', 'AuthController@logout'); $api->post('refresh', 'AuthController@refresh'); $api->post('me', 'AuthController@me'); $api->get('test', 'AuthController@test'); }); 複製程式碼
設定了這幾個路由,對應的url類似這樣: www.yourweb.com/api/me 使用postman來除錯這些API。
請求API的大致流程
我們使用jwt代替session,首先是通過登入(jwt的attempt方法驗證賬號密碼),成功後會返回一個JWT,我們把這個字串統一叫做token,這個token需要我們客戶端儲存起來,然後後面需要認證的介面就在請求頭裡帶上這個token,後臺驗證正確後就會進行下一操作,如果token錯誤,或者過期就返回401或500錯誤,拒絕後面的操作。
前端可以儲存在localStorage,小程式可以 使用wx.setStorageSync儲存
所以請求頭資訊Authorization:Bearer + token很重要,但是有個問題,這個token是有一個重新整理時間和過期時間的: 'ttl' => env('JWT_TTL', 60),
'refresh_ttl' => env('JWT_REFRESH_TTL', 20160),
- refresh_ttl是過期時間,預設14天,很好理解,就像一些網站一樣,你好幾個月沒去登入,你的賬號會自動退出登入,因為過期了,需要重新輸入賬號密碼登入。
- ttl重新整理時間預設60分鐘,也就是說你拿這個一小時前的token去請求是不行的,會報The token has been blacklisted的錯誤,意思是說這個舊的token已經被列入黑名單,無法使用
token是會被別人盜取的,所以token需要每隔一段時間就更新一次
這時候有個問題,每隔一小時就更新,那豈不是要每小時就重新登入一遍來獲取新token?當然不需要,我們可以寫個中介軟體來實現無痛重新整理token,使用者不會察覺我們已經更新了token。
<?php namespace App\Http\Middleware; use Closure; use Tymon\JWTAuth\Exceptions\JWTException; use Tymon\JWTAuth\Http\Middleware\BaseMiddleware; use Tymon\JWTAuth\Exceptions\TokenExpiredException; use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; class RefreshToken extends BaseMiddleware { /** * @author: zhaogx * @param $request * @param Closure $next * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response|mixed * @throws JWTException */ public function handle($request, Closure $next) { // 檢查此次請求中是否帶有 token,如果沒有則丟擲異常。 $this->checkForToken($request); // 使用 try 包裹,以捕捉 token 過期所丟擲的 TokenExpiredException異常 try { // 檢測使用者的登入狀態,如果正常則通過 if ($this->auth->parseToken()->authenticate()) { return $next($request); } throw new UnauthorizedHttpException('jwt-auth', '未登入'); } catch (TokenExpiredException $exception) { // 此處捕獲到了 token 過期所丟擲的 TokenExpiredException 異常,我們在這裡需要做的是重新整理該使用者的 token 並將它新增到響應頭中 try { // 重新整理使用者的 token $token = $this->auth->refresh(); // 使用一次性登入以保證此次請求的成功 \Auth::guard('api')->onceUsingId($this->auth->manager()->getPayloadFactory()->buildClaimsCollection()->toPlainArray()['sub']); } catch (JWTException $exception) { // 如果捕獲到此異常,即代表 refresh 也過期了,使用者無法重新整理令牌,需要重新登入。 throw new UnauthorizedHttpException('jwt-auth', $exception->getMessage()); } } return $next($request)->withHeaders([ 'Authorization'=> 'Bearer '.$token, ]); } } 複製程式碼
一旦中介軟體檢測到token過時了,就自動重新整理token,然後在響應頭把新的token返回來,我們客戶端可以根據響應頭是否有'Authorization'來決定是否要替換token 在使用postman除錯這些API的時候就有個問題,postman又沒有前端程式碼,我怎麼及時更新這個token,難道每次請求都要去看響應頭,發現Authorization後手動去複製黏貼嗎,當然也不需要,postman有個強大的環境變數,其實也是前端js的東西。
postman自動重新整理請求頭token
登入後自動獲取token
首先點選設定環境這個按鈕,點選Add按鈕新增一個變數,我們設定key值為access_token,


接著我們在登入介面的Tests中去賦值這個變數

var data = JSON.parse(responseBody); if (data.result.access_token) { tests["Body has token"] = true; var tokenArray = data.result.access_token.split(" "); postman.setEnvironmentVariable("access_token", tokenArray[1]); } else { tests["Body has token"] = false; } 複製程式碼
這段js程式碼就是獲取請求成功後返回的access_token值,將其賦值給postman的環境變數,我們看到請求成功後我們後臺返回了一個json,其中就有我們需要的access_token,我們可以再去環境變數那裡看看這時候的變數有什麼變化

可以看到這裡的變數access_token已經有值了,就是我們後臺返回來的access_token字串,說明賦值成功
接著我們到另一個需要認證的介面測試 我們在Authorization型別type選擇Bearer Token,在後面Token表單那裡打一個'{'就會自動提示我們設定過的變數{{access_token}}

傳送請求測試下

已經成功了。
無痛重新整理token
那如果token重新整理了,經過後臺中間件無痛重新整理後,會在響應頭返回一個新的token(這一次請求用的是舊的token,預設認證通過)

現在我們需要在這個介面上直接更新我們的變數access_token(如下圖),而不需要去再請求一遍登入介面

var authHeader = postman.getResponseHeader('Authorization'); if (authHeader){ var tokenArray = authHeader.split(" "); postman.setEnvironmentVariable("access_token", tokenArray[1]); tests["Body has refreshtoken"] = true; } else { tests["Body has no refreshtoken"] = false; } 複製程式碼
這段js程式碼就是將響應頭中的Authorization賦值給我們的access_token

這是響應頭的Authorization,截取了最後面的字串

重新整理時間過了後,我們試著再發一次請求,我們可以看到,還是可以訪問的,而且請求頭裡的Authorization已經自動更新過來了
用一句話整理大概就是,你需要在哪個介面響應後更新變數,就去這個這個口的Test下寫js賦值程式碼 postman.setEnvironmentVariable("access_token", token);
,只要沒錯誤你就可以在別的地方使用{{access_token}}更新替換了。