使用postman調試jwt開發的接口

上一篇博客文章https://segmentfault.com/a/11... 介紹了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類似這樣:http://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,
1
2

接着我們在登錄接口的Tests中去賦值這個變量
3

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,我們可以再去環境變量那裏看看這時候的變量有什麼變化
4

可以看到這裏的變量access_token已經有值了,就是我們後臺返回來的access_token字符串,說明賦值成功

接着我們到另一個需要認證的接口測試
我們在Authorization類型type選擇Bearer Token,在後面Token表單那裏打一個'{'就會自動提示我們設置過的變量{{access_token}}
5
發送請求測試下
6
已經成功了。

無痛刷新token

那如果token刷新了,經過後臺中間件無痛刷新後,會在響應頭返回一個新的token(這一次請求用的是舊的token,默認認證通過)
7

現在我們需要在這個接口上直接更新我們的變量access_token(如下圖),而不需要去再請求一遍登錄接口
10

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
8

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

刷新時間過了後,我們試着再發一次請求,我們可以看到,還是可以訪問的,而且請求頭裏的Authorization已經自動更新過來了

用一句話整理大概就是,你需要在哪個接口響應後更新變量,就去這個這個口的Test下寫js賦值代碼
postman.setEnvironmentVariable("access_token", token);,只要沒錯誤你就可以在別的地方使用{{access_token}}更新替換了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章