使用postman调试jwt开发的接口

个人github博客: https://zgxxx.github.io/

上一篇博客文章https://segmentfault.com/a/11... 介绍了laravel使用dingo+jwt开发API的几个步骤,那么在实际操做中,咱们须要测试APIphp

$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错误,拒绝后面的操做。laravel

前端能够保存在localStorage,小程序能够 使用wx.setStorageSync保存

因此请求头信息Authorization:Bearer + token很重要,可是有个问题,这个token是有一个刷新时间和过时时间的:
'ttl' => env('JWT_TTL', 60),
'refresh_ttl' => env('JWT_REFRESH_TTL', 20160),git

  • refresh_ttl是过时时间,默认14天,很好理解,就像一些网站同样,你好几个月没去登陆,你的帐号会自动退出登陆,由于过时了,须要从新输入帐号密码登陆。
  • ttl刷新时间默认60分钟,也就是说你拿这个一小时前的token去请求是不行的,会报The token has been blacklisted的错误,意思是说这个旧的token已经被列入黑名单,没法使用
token是会被别人盗取的,因此token须要每隔一段时间就更新一次

这时候有个问题,每隔一小时就更新,那岂不是要每小时就从新登陆一遍来获取新token?固然不须要,咱们能够写个中间件来实现无痛刷新token,用户不会察觉咱们已经更新了token。github

<?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的东西。web

postman自动刷新请求头token

登陆后自动获取token

首先点击设置环境这个按钮,点击Add按钮添加一个变量,咱们设置key值为access_token,
1
2json

接着咱们在登陆接口的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,咱们能够再去环境变量那里看看这时候的变量有什么变化
4segmentfault

能够看到这里的变量access_token已经有值了,就是咱们后台返回来的access_token字符串,说明赋值成功api

接着咱们到另外一个须要认证的接口测试
咱们在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}}更新替换了。

相关文章
相关标签/搜索