access_token是客户端调用其他微服务调的凭证,access_token有效期不能太长(丢了风险很大),一般可以设置2小时,如果access_token失效了,就不能调用微服务了,上节说了access_token失效的处理---refresh_token来刷新令牌,refresh_token可以设置很长的有效期,比如一个月
下面是用refresh_token刷新令牌的步骤:
1,配置refresh_token
在客户端应用的表里配置 refresh_token 的有效期,然后配置refresh_token授权模式,这样认证服务器在给客户端应用发access_token的同时,也会发一个refresh_token
(图1)
2, 在客户端应用调用微服务时,从session中拿出token,判token是否过期(在存入session时已经设置了token的过期时间),如果token已过期,就从拿refresh_token换取access_token:
(图2)
如果refresh_token也过期了怎么处理呢?
虽然refresh_token有效期很长(比如一个月)但是还是会过期的。如果refresh_token也过期了怎么办呢?
答案是:没办法。只能去认证服务器走一遍认证流程。
当重新去认证服务器走授权流程的时候,又分两种情况:
1,refresh_token虽然过期了,但是认证服务器上的session还没过期,走认证流程的时候,认证服务器直接返回一个令牌给客户端应用。
2,refresh_token虽然过期了,认证服务器上的session也过期了,那就必须让用户输入用户名密码,进行重新登录。
情况1可以控制让用户重新输入用户名密码进行重新登录,一旦refresh_token过期了,走一遍退出流程,让用户重新登录(我感觉这样挺好,见过很多应用app也是,一个月登录就失效了)
开始实验
1,客户端应用代码
直到上节为止,架构是这样的:在认证服务器登录成功后,客户端应用将认证服务器返回的token存到了自己的session,当调用微服务时,从session中拿出token,放在请求头。如果token已经过期了,就拿refresh_token去认证服务器刷新令牌,然后将新获取的token存到自己的session,并携带新的token去调用微服务。(如图1),刷新令牌失效会哪个地方发生?就在拿着refresh_token去刷新令牌的时候,refresh_token 可以也已经过期,此时就要捕获到这个异常,在刷新令牌的时候,发现refresh_token也过期了,就返回给前端一个500响应码和一个错误信息,前端拿到这个响应码,就去认证服务器走一遍退出流程,让用户彻底退出系统。
图1改造后的代码如下所示
(图3)
2,表配置
在客户端应用里,将admin应用的token有效期设为10秒,refresh_token 有效期设为20秒。这样登录后10秒后,token就失效了,再调用订单服务,就会走上边说的刷新token代码,直到20秒后,刷新令牌也失效了,给前端一个错误码500和一个message,前端全局拦截这个错误,调用退出方法。
3,前端代码
搞一个全局拦截器,拦截refresh_token失效的响应,因为调用任何服务,都可能返回这个错误响应。
这里使用jquery做的实验(我不会vue和angular),如果是vue获取angular等目前比较流行的框架,思路也是一样的。
4,现象
启动几个微服务,登录后调用订单服务,正常
token 10秒过期后,refresh_token起效了,刷新了令牌
20秒后,调用订单服务,自动走退出流程,跳转admin应用的登录页
如果refresh_token 失效,还想去认证服务器看看认证服务器的session失效没失效,那就在全局拦截出改成如下代码(我感觉这种体验并不好):
本节github代码:https://github.com/lhy1234/springcloud-security/tree/chapt-5-6-refreshtoken-expired 写文章不易,如果对你有帮助了,给个小星星吧!
欢迎关注个人公众号一起交流学习: