Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

重复请求会不会生成多个token #14

Closed
javabye opened this issue Mar 28, 2019 · 10 comments
Closed

重复请求会不会生成多个token #14

javabye opened this issue Mar 28, 2019 · 10 comments

Comments

@javabye
Copy link

javabye commented Mar 28, 2019

同一个页面一般情况下都会同时请求多个后台接口,当accessToken失效的时候,同时有多个请求,后端会不会刷新出多个newtoken的问题?

@javabye
Copy link
Author

javabye commented Apr 4, 2019

防止重复刷新accessToken,有什么解决方案吗?

@dolyw
Copy link
Owner

dolyw commented Apr 4, 2019

正常情况下是不会的,多个请求下,某一个一旦刷新了AccessToken,其他请求如果不是携带最新的AccessToken是无法通过验证的

@kangyunjie
Copy link

那一个页面请求多个接口,第一个接口把token刷新了。后面不就请求失败了吗?

@dolyw
Copy link
Owner

dolyw commented Apr 9, 2019

那一个页面请求多个接口,第一个接口把token刷新了。后面不就请求失败了吗?

一般同时请求多个接口应该是只有axios可以吧,应该可以异步回调解决吧,这是前端处理了,我前端不是很熟

@kangyunjie
Copy link

OK 好的,暂时还没遇到这种问题。以后观察看看

@dolyw
Copy link
Owner

dolyw commented May 15, 2019

其实token失效,自动刷新token,在页面只有一个请求的时候是比较好处理的,但是如果页面同时有多个请求,并且前面的请求正好产生token失效,这就需要一些稍微复杂的处理

解决方式主要是用了Promise 函数来进行处理。前端每一个token失效的请求(后端返回状态码给前端,知道这个请求是token过期了)都会存到一个Promise函数集合里面,当刷新token的函数执行完毕后,才会批量再执行这些Promise函数,返回请求结果。还有一点要注意一下,这儿设置一个刷新token的开关isRefreshing,这个是非常有必要的,防止重复请求

详细链接:https://segmentfault.com/a/1190000016946316

@kigangka
Copy link

kigangka commented May 28, 2019

@javabye 我也遇到这样的问题了,多个请求同时访问,正好refreshToken失效,前一个请求更新了refreshToken和accessToken,后一个请求就报出失效错误了,这是因为,前一个请求流程还没有走完回到前端,没来的及更新前端的accessToken,后一个请求带着之前旧的的accessToken请求就来了,而此时前一个请求已经更新了refreshToken,自然和后一个请求accessToken里的时间戳对不上了。下面说下我的解决方案,希望大家提提意见,方法是服务始终保留两个时间戳,简单的画了个图,
image
① 登录获取token1,存储到前端,下次请求都带token1,服务器存储timestamp1;
② 在token1正好失效时间点,多个请求同时访问服务器,请求A先被捕获到超时,要更新accessToken,取出服务器存放的时间戳,逗号分割后数组,如果此时只有一个时间戳,那就直接生成一个新的时间戳timestamp2,生成新accessToken,token2,此时把timestamp1和timestamp2,一起存储在服务端,请求A返回新的token2,此时,请求B过来后,发现token1过期,进入刷新方法,一样,拿出服务器中的时间戳,此时时间戳为timestamp1,timestamp2,我们发现和数组前一个时间戳一致,就直接请求放行,不再做refreshToken操作,正常业务结束后返回前端;
③ token2正好失效的时间点,请求C和D同时访问服务器端,请求C先被捕获超时需要更新,此时发现时间戳与服务的timestamp1,timestamp2数组后一个相等,那么生成新的timestamp3,生成新的accessToken token3,服务端refreshToken时间戳变成timestamp2,timestamp3,请求D进来后发现与数组前一个timestamp2相等,直接放行,不再做refreshToken操作,正常业务结束后返回前端。

@dolyw
Copy link
Owner

dolyw commented Jul 3, 2019

@javabye 我也遇到这样的问题了,多个请求同时访问,正好refreshToken失效,前一个请求更新了refreshToken和accessToken,后一个请求就报出失效错误了,这是因为,前一个请求流程还没有走完回到前端,没来的及更新前端的accessToken,后一个请求带着之前旧的的accessToken请求就来了,而此时前一个请求已经更新了refreshToken,自然和后一个请求accessToken里的时间戳对不上了。下面说下我的解决方案,希望大家提提意见,方法是服务始终保留两个时间戳,简单的画了个图,
image
① 登录获取token1,存储到前端,下次请求都带token1,服务器存储timestamp1;
② 在token1正好失效时间点,多个请求同时访问服务器,请求A先被捕获到超时,要更新accessToken,取出服务器存放的时间戳,逗号分割后数组,如果此时只有一个时间戳,那就直接生成一个新的时间戳timestamp2,生成新accessToken,token2,此时把timestamp1和timestamp2,一起存储在服务端,请求A返回新的token2,此时,请求B过来后,发现token1过期,进入刷新方法,一样,拿出服务器中的时间戳,此时时间戳为timestamp1,timestamp2,我们发现和数组前一个时间戳一致,就直接请求放行,不再做refreshToken操作,正常业务结束后返回前端;
③ token2正好失效的时间点,请求C和D同时访问服务器端,请求C先被捕获超时需要更新,此时发现时间戳与服务的timestamp1,timestamp2数组后一个相等,那么生成新的timestamp3,生成新的accessToken token3,服务端refreshToken时间戳变成timestamp2,timestamp3,请求D进来后发现与数组前一个timestamp2相等,直接放行,不再做refreshToken操作,正常业务结束后返回前端。

这有一点点复杂啊,哈哈,不过写一次就好了,好像看这个,前端也可以处理的:https://segmentfault.com/a/1190000016946316

@dolyw
Copy link
Owner

dolyw commented Jul 3, 2019

@javabye 我也遇到这样的问题了,多个请求同时访问,正好refreshToken失效,前一个请求更新了refreshToken和accessToken,后一个请求就报出失效错误了,这是因为,前一个请求流程还没有走完回到前端,没来的及更新前端的accessToken,后一个请求带着之前旧的的accessToken请求就来了,而此时前一个请求已经更新了refreshToken,自然和后一个请求accessToken里的时间戳对不上了。下面说下我的解决方案,希望大家提提意见,方法是服务始终保留两个时间戳,简单的画了个图,
image
① 登录获取token1,存储到前端,下次请求都带token1,服务器存储timestamp1;
② 在token1正好失效时间点,多个请求同时访问服务器,请求A先被捕获到超时,要更新accessToken,取出服务器存放的时间戳,逗号分割后数组,如果此时只有一个时间戳,那就直接生成一个新的时间戳timestamp2,生成新accessToken,token2,此时把timestamp1和timestamp2,一起存储在服务端,请求A返回新的token2,此时,请求B过来后,发现token1过期,进入刷新方法,一样,拿出服务器中的时间戳,此时时间戳为timestamp1,timestamp2,我们发现和数组前一个时间戳一致,就直接请求放行,不再做refreshToken操作,正常业务结束后返回前端;
③ token2正好失效的时间点,请求C和D同时访问服务器端,请求C先被捕获超时需要更新,此时发现时间戳与服务的timestamp1,timestamp2数组后一个相等,那么生成新的timestamp3,生成新的accessToken token3,服务端refreshToken时间戳变成timestamp2,timestamp3,请求D进来后发现与数组前一个timestamp2相等,直接放行,不再做refreshToken操作,正常业务结束后返回前端。

想了一下还是后端处理最安全,前端处理还是不行

@dolyw dolyw closed this as completed Aug 26, 2019
Repository owner deleted a comment from youthlql Jan 3, 2020
@dolyw
Copy link
Owner

dolyw commented Jan 3, 2020

重新开了一个 Issues,说明了前端还有后端怎么解决 Token 刷新下,并发请求怎么处理的问题

就是同时多个请求,第一个请求刷新了 Token,后面的请求还是携带的刷新前的旧 Token 就无法通过,该怎么处理

#29 Token刷新并发处理

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants