个人github博客:zgxxx.github.io/php
上一篇博客文章 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。laravel
咱们使用jwt代替session,首先是经过登陆(jwt的attempt方法验证帐号密码),成功后会返回一个JWT,咱们把这个字符串统一叫作token,这个token须要咱们客户端保存起来,而后后面须要认证的接口就在请求头里带上这个token,后台验证正确后就会进行下一操做,若是token错误,或者过时就返回401或500错误,拒绝后面的操做。git
前端能够保存在localStorage,小程序能够 使用wx.setStorageSync保存github
因此请求头信息Authorization:Bearer + token很重要,可是有个问题,这个token是有一个刷新时间和过时时间的: 'ttl' => env('JWT_TTL', 60),
'refresh_ttl' => env('JWT_REFRESH_TTL', 20160),
web
token是会被别人盗取的,因此token须要每隔一段时间就更新一次json
这时候有个问题,每隔一小时就更新,那岂不是要每小时就从新登陆一遍来获取新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的东西。api
首先点击设置环境这个按钮,点击Add按钮添加一个变量,咱们设置key值为access_token, bash
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,咱们能够再去环境变量那里看看这时候的变量有什么变化
接着咱们到另外一个须要认证的接口测试 咱们在Authorization类型type选择Bearer Token,在后面Token表单那里打一个'{'就会自动提示咱们设置过的变量{{access_token}}
那若是token刷新了,通过后台中间件无痛刷新后,会在响应头返回一个新的token(这一次请求用的是旧的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
用一句话整理大概就是,你须要在哪一个接口响应后更新变量,就去这个这个口的Test下写js赋值代码 postman.setEnvironmentVariable("access_token", token);
,只要没错误你就能够在别的地方使用{{access_token}}更新替换了。