博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
API 开发中可选择传递 token 接口遇到的一个坑
阅读量:7022 次
发布时间:2019-06-28

本文共 3708 字,大约阅读时间需要 12 分钟。

  1. 在做 API 开发时,不可避免会涉及到登录验证,我使用的是
  2. 在登录中会经常遇到一个token过期的问题,在config/jwt.php默认设置中,这个过期时间是一个小时,不过为了安全也可以设置更小一点,我设置了为五分钟。
  3. 五分钟过期,如果就让用户去登录,这种体验会让用户直接抛弃你的网站,所以这就会使用到刷新token这个功能
  4. 正常情况下是写一个刷新token的接口,当过期的时候前端把过期的token带上请求这个接口换取新的token
  5. 不过为了方便前端也可以使用后端刷新返回,直至不可刷新,我用的就是这个方法:
  6. 而坑就是这样来的,
  • 在必须需要登录验证的接口设置刷新token
checkForToken($request); try { /**************************************** * 尝试通过 tokne 登录,如果正常,就获取到用户 * 无法正确的登录,抛出 token 异常 ****************************************/ if ($this->auth->parseToken()->authenticate()) { return $next($request); } throw new UnauthorizedHttpException('jwt-auth', 'User not found'); } catch (TokenExpiredException $e) { try { /**************************************** * token 过期的异常,尝试刷新 token * 使用 id 一次性登录以保证此次请求的成功 ****************************************/ $token = $this->auth->refresh(); $id = $this->auth ->manager() ->getPayloadFactory() ->buildClaimsCollection() ->toPlainArray()['sub']; auth()->onceUsingId($id); } catch (JWTException $e) { /**************************************** * 如果捕获到此异常,即代表 refresh 也过期了, * 用户无法刷新令牌,需要重新登录。 ****************************************/ throw new UnauthorizedHttpException('jwt-auth', $e->getMessage(), null, StatusServe::HTTP_PAYMENT_REQUIRED); } } // 在响应头中返回新的 token return $this->setAuthenticationHeader($next($request), $token); }}复制代码
  • 而有些页面,比如文章列表页面,这个接口登录与不登录皆可访问,不过登录的时候可以在页面上显示是否点赞了这篇文章。所以这个接口直接使用的是jwt-auth默认的option中间件
* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */namespace Tymon\JWTAuth\Http\Middleware;use Closure;use Exception;class Check extends BaseMiddleware{ /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * * @return mixed */ public function handle($request, Closure $next) { if ($this->auth->parser()->setRequest($request)->hasToken()) { try { $this->auth->parseToken()->authenticate(); } catch (Exception $e) { } } return $next($request); }}复制代码
  1. 一开始也没有发现问题,直到测试的时候,发现文章列表页面点赞过的文章,过了一段时间再刷新的时候发现不显示已点赞,但是进入个人中心的已点赞文章可以看到。
  2. 刚开始测试没找出原因,直接暴力调试代码,发现没获取到登录用户,一想不对呀,已经传token为何获取不到。经过发现,去到个人中心,再回到新闻列表页就可以正常显示,过了一段时间又不显示了。
  3. 经过这一轮之后,大概明白,在新闻列表页时,token已经过期,但是当时图方便用的jwt-auth默认的中间件,不会刷新token,所以这个接口获取不到登录的用户。当进入个人中心,发现当前token已经过期,后台刷新token返回,这时候再回到文章列表页就可以得到正常的数据,一段时间后,token又失效了,所以有无法看到点赞过的文章
  4. 解决方法,自己写一个option中间件,当存在token的时候,也需要做token刷新处理。
auth->parser()->setRequest($request)->hasToken()) { try { $this->auth->parseToken()->authenticate(); } catch (TokenExpiredException $e) { // 此处做刷新 token 处理 // 具体代码可以参考必须需要登录验证的接口 // 在响应头中返回新的 token return $this->setAuthenticationHeader($next($request), $token); } catch (Exception $e) { } } return $next($request); }}复制代码

问题解决。 最后说一个并发会出现的问题:

# 当前 token_1 过期,先发起 a 请求,之后马上发起 b 请求# a 请求到服务器,服务器判断过期,刷新 token_1# 之后返回 token_2 给 a 请求响应# 这时候迟一点的 b 请求用的还是 token_1 # 服务器已经将此 token_1 加入黑名单,所以 b 请求无效       token_1         刷新返回 token_2a 请求 --------> server -------> 成功       token_1         过期的 token_1,应该使用 token_2b 请求 --------> server ------> 失败复制代码

已经想到这种情况,我们只需要设置一个黑名单宽限时间即可

我设置为
5秒,就是当
token_1过期了,你还能继续使用
token_1操作
5秒时间

转载地址:http://undxl.baihongyu.com/

你可能感兴趣的文章
动画-CAShapeLayer实现QQ消息红点拖拽效果
查看>>
Apache配置文件详解
查看>>
Linux命令:自动添加用戶
查看>>
我的友情链接
查看>>
Skype for Business后端服务器部署AlwaysOn可用性组实战篇
查看>>
快速理解什么是APT
查看>>
关于error LNK20xx的链接错误
查看>>
【物联网智能网关-08】TinyGUI和WPF汉字显示技术比较
查看>>
linux学习日志
查看>>
Linux 常用命令
查看>>
jquery如何操作cookie
查看>>
手机号校验
查看>>
表格批量修改数据
查看>>
中国的农村在以后会很有市场?
查看>>
第六章TCP和UDP基本原理(续)
查看>>
symantec5220牛刀小试系列(4)
查看>>
Go笔记-flag参数解析
查看>>
二分查找例子 记录一下
查看>>
printf的返回值问题(转)
查看>>
常用选择器
查看>>