如何以及为啥使用 refresh_token 处理 jwt 令牌过期,还有另一种选择吗? [关闭]

Posted

技术标签:

【中文标题】如何以及为啥使用 refresh_token 处理 jwt 令牌过期,还有另一种选择吗? [关闭]【英文标题】:How and why handle jwt token expiration with refresh_token, is there another alternative? [closed]如何以及为什么使用 refresh_token 处理 jwt 令牌过期,还有另一种选择吗? [关闭] 【发布时间】:2020-11-19 03:37:50 【问题描述】:

我有两场战争:app.war(struts web app)和rest.war(classic rest api)。

app.war通过用户登录app.war成功后生成的jwt令牌访问rest.war

当用户使用a.war时,需要通过a.war的jsp用jwt令牌发送ajax调用从rest.war获取一些数据。

jwt token的过期时间为15分钟,而app.war的会话超时时间为1小时。

但是,如果 jwt 令牌已过期,即使弹出要求用户再次登录,用户仍然可以访问app.war

还有一种选择:使用access_tokenrefresh_token,如果access_token过期,则使用refresh_token获取新的access_tokenrefresh_token

对于这种方法,我有一些疑问:

首先,为什么要使用两个令牌?因为我认为它们是相同的,只是refresh_tokenaccess_token 寿命更长并使用refresh_token 来获得新的access_token,那么为什么不只是access_token 并将其过期时间设置得更长呢?

第二access_tokenrefresh_token的生成算法是不是一样,只是过期时间不一样?

第三,如果客户端使用token执行了多次api调用(同步和异步),如果其中一次调用返回401(token过期)如何处理?

【问题讨论】:

我不知道为什么它被关闭了。我认为它只关注一个问题:jwt token expired。 【参考方案1】:

如您所说,refresh_token 是处理 jwt 过期的推荐替代方法。

为什么要使用两个令牌?

因为使用两个令牌(access_token 和 refresh_token)是世界级公司(google、azure、amazon 等)使用的经过验证的策略,它们信任 OAuth 2.0 授权框架

https://www.rfc-editor.org/rfc/rfc6749

它是互联网工程任务组 (IETF) 的产物,而后者又是:互联网工程任务组 (IETF) 是一个开放的标准组织,它开发和推广自愿性互联网标准,特别是构成互联网协议套件。

您可以使用严格遵守其specification 的 oauth2 框架,创建并混合关注您的自定义需求或开发具有新概念的新框架

那么为什么不只是 access_token 并将其过期时间设置得更长呢?

Oauth2 规范不推荐使用不可过期的令牌。标记词本身意味着一个可过期的东西。如果它没有过期,我们可以使用密码。

例如,让我们想象一个需要令牌来下载一些用户信息的移动应用。如果令牌没有过期,小偷可以窃取移动应用程序,输入并访问用户信息。但由于令牌意味着到期,小偷可能有时间限制的访问权限。此外,用户在窃取时令牌可能是revoked,因此小偷无法访问。

通常当令牌过期时,会强制登录。但是有一些要求,用户不想每 3600 毫秒再次登录和登录。因此,refresh_token 有助于不打扰我们的用户并无需人工登录即可获得新的 access_token。现在,如果 refresh_token 没有过期会怎样?我们可以创建几个月或几年的访问令牌吗?这就是为什么 refresh_token 也必须过期

access_token和refresh_token的生成算法是一样的,只是过期时间不同?

我实现了一种安全服务器,并使用了相同的算法,但过期时间不同。但是我添加了一个额外的声明来区分它们:

How to differentiate refresh_token from access_token at validation stage in security server?

多次调用需要access_token

在这种情况下,如果在每次用户登录时更新令牌,您将拥有一个可以使用 3600 毫秒的 access_token。

之后,您的用户是一种机器人(或者是您网络的功能/要求)并开始使用多种表单,这些表单对附加 access_token 的 rest api 执行多次调用。

如果我们在 3601ms,在下一次从 web 调用 api 时,api 必须返回 403 错误并显示经典的弹窗:Session expired, click here to login...

如果您的要求是避免此弹出窗口,您可以选择以下方法之一:

使用刷新令牌更新令牌时出现 403 错误。在这种情况下,您可以使用axios-retry 来处理错误重试。 登录后,启动异步任务以在小于令牌到期时间的间隔内更新令牌。在我们的示例中为 3400 毫秒。因此,来自您的网络的 api 调用永远不会失败

建议

在后端层执行 access_token 和 refresh_token 交换,而不是在前端 (ajax) 层。

因此攻击者永远不会知道您的端点来获取令牌或刷新它们。

【讨论】:

感谢您的详细回答。你说Perform access_token and refresh_token exchange in your backend layer, not in frontend (ajax) layer.,什么意思?你的意思是access_tokenrefresh_token 不应该存储在用户客户端中,这样前端(ajax)就不需要发送它们? 不知道为什么关了,如果关了不知道赏金能不能分配给你。对此感到抱歉。 我试图改善你的问题。我认为这是一个有效的方法,可以帮助其他人了解refresh_token 的工作原理,但里面有几个问题:s

以上是关于如何以及为啥使用 refresh_token 处理 jwt 令牌过期,还有另一种选择吗? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Google api refresh_token null 以及如何刷新访问令牌

在 React Native 中处理刷新令牌

为啥 context.startActivity(intent) 没有启动活动以及如何在 android 中处理异常?

使用带有 OpenID Connect 提供程序的 spring-security-oauth2 客户端时如何访问“id_token”和“refresh_token”?

jwt中为什么用refresh_token去刷新access_token,直接把access_token的有效期设置长一点不行吗?

我想了解为啥要创建一种类型来处理 Go 中的错误以及您如何决定它应该具有啥基础类型