文档章节

API 开发中可选择传递 token 接口遇到的一个坑

等月人
 等月人
发布于 06/24 12:24
字数 1328
阅读 10
收藏 1
点赞 0
评论 2
JWt
  1. 在做 API 开发时,不可避免会涉及到登录验证,我使用的是jwt-auth
  2. 在登录中会经常遇到一个token过期的问题,在config/jwt.php默认设置中,这个过期时间是一个小时,不过为了安全也可以设置更小一点,我设置了为五分钟。
  3. 五分钟过期,如果就让用户去登录,这种体验会让用户直接抛弃你的网站,所以这就会使用到刷新token这个功能
  4. 正常情况下是写一个刷新token的接口,当过期的时候前端把过期的token带上请求这个接口换取新的token
  5. 不过为了方便前端也可以使用后端刷新返回,直至不可刷新,我用的就是这个方法:使用 Jwt-Auth 实现 API 用户认证以及无痛刷新访问令牌
  6. 而坑就是这样来的,
  • 在必须需要登录验证的接口设置刷新token
<?php

namespace App\Http\Middleware;

use App\Services\StatusServe;
use Closure;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;

class CheckUserLoginAndRefreshToken extends BaseMiddleware
{
    /**
     * 检查用户登录,用户正常登录,如果 token 过期
     * 刷新 token 从响应头返回
     *
     * @param         $request
     * @param Closure $next
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
     * @throws JWTException
     */
    public function handle($request, Closure $next)
    {
        /****************************************
         * 检查token 是否存在
         ****************************************/
        $this->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中间件
<?php

/*
 * This file is part of jwt-auth.
 *
 * (c) Sean Tymon <tymon148@gmail.com>
 *
 * 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刷新处理。
<?php

namespace App\Http\Middleware;

use Closure;
use Exception;

class Check extends BaseMiddleware
{

    public function handle($request, Closure $next)
    {
        if ($this->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_2
a 请求 --------> server -------> 成功
       token_1         过期的 token_1,应该使用 token_2
b 请求 --------> server ------> 失败

jwt-auth已经想到这种情况,我们只需要设置一个黑名单宽限时间即可 我设置为5秒,就是当token_1过期了,你还能继续使用token_1操作5秒时间

原文地址

© 著作权归作者所有

共有 人打赏支持
等月人
粉丝 1
博文 11
码字总数 9006
作品 2
南宁
加载中

评论(2)

等月人
等月人

引用来自“松竹斋”的评论

你在过期的token中返回新的token 不会有问题么?

别人截取到你的已过期token ,发一次请求就可以获取到你的正常token,感觉安全隐患很大啊
过期的 token 是五分钟,如果五分钟过期了,用旧 token 换取新的 token 有条件的,如果都是已经旧的 token 请求换取新的 token。旧的 token 会被拉入黑名单。但并发会出现问题,所以旧的 token 可以设置几秒钟并发时间
松竹斋
松竹斋
你在过期的token中返回新的token 不会有问题么?

别人截取到你的已过期token ,发一次请求就可以获取到你的正常token,感觉安全隐患很大啊
微信支付2016开发调试过程记录

最近换了家公司,因为以前也是做支付的来这个公司直接让我从零开始搭建支付服务。首先是微信支付宝的第三方接入。我是做java开发的。支付宝有接入的sdk就是一个jar包。而且有沙箱环境测试帐号...

挨踢人生
2016/11/15
0
0
谈谈API版本控制的策略

上篇写《聊聊数据库和缓存同步机制》的时候,收到一份读者留言,希望我来谈谈API开发过程中的版本控制。这是一个很好的话题,对于任何互联网产品,随着需求的改进,都会遇到同样的问题,我自...

谢东升Forest
2017/07/26
0
0
基于Koa.js的微信工具类小记

关于微信公众号开发和小程序开发的教程其实网上已经有很多了,但是基于koa.js 开发的教程其实不多,于是接下来对踩坑的经历做一些小结; 自己也写了一个微信工具类,项目地址是微信工具类 ...

evont
07/09
0
0
七牛云模块化文档

前言 闲来无事,搭建了个人私仓来放模块化项目,以便项目引入直接使用。关键是,模块化可以根据项目所需进行版本迭代,每一次的使用都是完善的根基,效果贼棒。 介绍 七牛云是国内领先的企业...

Joryun刘家源
01/02
0
0
layui文件上传upload跨域回调问题解决方案

最近在开发一个项目,项目是由api接口端和页面展现端组成的,也就是api接口和页面是不同子域名。如:api.abc.com和admin.abc.com。 在使用layui的upload组件时遇到了跨域问题,上layui的git...

宇润
2017/04/08
990
1
认证鉴权与API权限控制在微服务架构中的设计与实现(四)

引言: 本文系《认证鉴权与API权限控制在微服务架构中的设计与实现》系列的完结篇,前面三篇已经将认证鉴权与API权限控制的流程和主要细节讲解完。本文比较长,对这个系列进行收尾,主要内容...

aoho
2017/10/26
0
0
群发图文规则

群发图文 1、如果群发内容中包含图片,必须上传到微信服务器接口 https://api.weixin.qq.com/cgi-bin/media/uploadimg?accesstoken=ACCESSTOKEN 2、上传图文接口 https://api.weixin.qq.com/...

CurtainRight
2016/01/13
77
0
anziguoer/wechatPay

#wechatPay nodejs 微信公众号支付开发 NodeJs 微信公众号功能开发,移动端 H5页面调用微信的支付功能。这几天根据公司的需要使用 node 和 h5页面调用微信的支付功能完成支付需求。现在把开发...

anziguoer
2016/09/15
0
0
nodejs 微信公众号支付开发

nodejs 微信公众号支付开发 NodeJs 微信公众号功能开发,移动端 H5页面调用微信的支付功能。这几天根据公司的需要使用 node 和 h5页面调用微信的支付功能完成支付需求。现在把开发过程重新捋一...

anziguoer
2016/09/14
980
0
致大神们:微博授权问题

最近想写一个新浪微博的应用,首先要获取用户的授权,可是现在连怎么发送授权信息,怎么接收授权了的access_token都不知道 用的是javascipt,求大神给个详细的代码。。。 1.用XMLHTTPReques...

lcniuren33
2012/09/08
9.6K
5

没有更多内容

加载失败,请刷新页面

加载更多

下一页

虚拟机怎么安装vmware tools

https://blog.csdn.net/tjcwt2011/article/details/72638977

AndyZhouX
10分钟前
0
0
There is no session with id[xxx]

参考网页 https://blog.csdn.net/caimengyuan/article/details/52526765 报错 2018-07-19 23:04:35,330 [http-nio-1008-exec-8] DEBUG [org.apache.shiro.web.servlet.SimpleCookie] - Found......

karma123
11分钟前
0
0
vue-router懒加载

1. vue-router懒加载定义 当路由被访问的时候才加载对应组件 2. vue-router懒加载作用 当构建的项目比较大的时候,懒加载可以分割代码块,提高页面的初始加载效率。 ###3. vue-router懒加载实...

不负好时光
18分钟前
0
0
庆祝法国队夺冠:用Python放一场烟花秀

天天敲代码的朋友,有没有想过代码也可以变得很酷炫又浪漫?今天就教大家用Python模拟出绽放的烟花庆祝昨晚法国队夺冠,工作之余也可以随时让程序为自己放一场烟花秀。 这个有趣的小项目并不...

猫咪编程
20分钟前
0
0
SpringBoot | 第七章:过滤器、监听器、拦截器

前言 在实际开发过程中,经常会碰见一些比如系统启动初始化信息、统计在线人数、在线用户数、过滤敏高词汇、访问权限控制(URL级别)等业务需求。这些对于业务来说一般上是无关的,业务方是无需...

oKong
33分钟前
5
0
存储结构分四类:顺序存储、链接存储、索引存储 和 散列存储

存储结构分四类:顺序存储、链接存储、索引存储 和 散列存储 存储结构分四类:顺序存储、链接存储、索引存储 和 散列存储。 顺序结构和链接结构适用在内存结构中。 顺序表每个单元都是按物理...

DannyCoder
44分钟前
1
0
Firefox 61已经为Ubuntu 提供支持

最新和最好的Mozilla Firefox 61 “Quantum”网络浏览器已经为Ubuntu Linux操作系统的用户提供了支持,现在可以通过官方软件库进行更新。 Mozilla于2018年6月26日发布了Firefox 61版本,该版...

六库科技
今天
0
0
Win10升级后执行系统封装(Sysprep)报错

开始封装 一年多以前开始给公司封装Win10系统,便于统一给公司电脑初始化携带各种软件的系统,致力于装完既可以开发的状态。那时候最新的版本是Win10 1703版本,自然就以他为母盘,然后结合V...

lyunweb
今天
40
0
php 性能优化

#什么情况下会遇到性能问题 PHP 语法使用的不恰当

to_be_better
今天
0
0
Jenkins 构建触发器操作详解

前言 跑自动化用例每次用手工点击jenkins出发自动化用例太麻烦了,我们希望能每天固定时间跑,这样就不用管了,坐等收测试报告结果就行。 一、定时构建语法 * * * * * (五颗星,中间用空格隔...

覃光林
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部