处理JWT到期和JWT有效负载更新
我有一个基于Koa的Node.js后端,用于我的个人/业余爱好应用程序。
我用JWT令牌实现会话处理。 客户端(AngularJS)在成功登录后获取令牌并将令牌存储在某处(目前在sessionStorage
但对于这个问题目的不重要)。
我有两个问题:
当我需要更新JWT代表的用户记录时,例如,用户打开双因素身份验证(2FA),所以我要求他提供他的电话号码,并且我想在用户记录中设置此电话号码。 目前,在成功验证电话号码后,我打电话给后台更新用户记录,并使用更新后的用户记录创建了新的JWT令牌(我从JWT令牌中排除了敏感信息,例如哈希密码,但我想包括客户端使用的电话号码)。 当某些凭证更改并使用此新令牌更新现有客户端令牌时,是否可以创建新令牌? 我是否永远不会创建另一个令牌,只有在成功验证后才创建一个令牌? 然后如何更新令牌中的有效负载?
我应该如何处理过期的JWT令牌? 在我看来,我有3个(可能的)场景:
2.1。 智威汤逊设置为短暂的生活,比如15分钟。 如果后端服务器回复401 Unauthenticated'Invalid token'(我猜这是koa-jwt
的默认行为),那么我会自动注销我的客户端并需要重新验证。 但是我也建立了一个互补的中间件,它是后端链中的最后一个,用刷新的到期来重新创建令牌,并且客户端也将用已刷新的令牌替换现有的令牌。 因此,如果用户处于活动状态并在每个受保护的API调用中使用该应用程序,那么在成功的情况下,将创建一个新的令牌来替换旧的令牌。
2.2。 JWT设置时间长,例如1周,如果到期,我会选择从客户端重新进行身份验证。
2.3。 复制https://tools.ietf.org/html/rfc6749#section-1.5。 在成功验证后创建JWT令牌时,我们发送access_token以及refresh_token。 当access_token过期并且服务器响应HTTP 401'无效标记'( koa-jwt
default)时,客户端将refresh_token发送到后端以要求新的access_token(以及可选的新的refresh_token)。 在这种情况下,我不完全了解refresh_token如何通过旧的access_token验证以提供新的令牌? 或者为什么我们需要有一个refresh_token?
关于上层主题(JWT更新和JWT到期)的任何通用建议都会有所帮助。
从底部开始,我会忽略刷新令牌,因为我认为他们不会帮助你。 它们通常针对客户端应用程序可以提供比用户浏览器更安全的存储的其他场景 - 考虑原生移动应用程序或服务器端Web应用程序。
刷新令牌是长期存在的 。 这意味着当客户端从服务器获取一个时,必须安全地存储此令牌以防止潜在攻击者使用它, 因此,将它们存储在浏览器中并不安全。
(重点是我的;源刷新标记)
这意味着选项2.3基本上与2.2相同,这不是一个错误的选项。 拥有长会话持续时间的Web应用程序并不罕见。 如果您的应用程序不是非常敏感,则可以使用长时间会话来改善用户体验。 例如,Django会话cookie的年龄默认为两周。 请参阅SESSION_COOKIE_AGE。
剩下的选项(2.1)通常被称为滑动会话。 会话超时很短,但只要用户在该时间间隔内继续使用应用程序,会话就会自动更新。 这可能是最常用的方法,或者至少是我最常用的方法,所以我很偏向。 我唯一需要注意的是,滑动会话通常使用存储在客户端的不透明会话标识符作为cookie,然后与存储在服务器上的实际会话数据一起实现。
您的方法有点不同,因为您拥有存储在浏览器本地存储上的无状态JWT令牌(它包含实际的用户数据)。 就像你说的,为了更新令牌,你必须生成一个新的令牌,因为你必须生成一个新的签名。
签名用于验证JWT的发件人是谁说的, 并确保邮件未被更改。
(重点是我的;源JSON网络令牌)
说了这么多,我会考虑以下几点:
话虽如此,你还应该认为智威汤逊并不是很大,但如果你决定自动更新,他们仍然是一个开销。 您可以通过选择20分钟的会话持续时间来缓解这一点,并且仅在会话过去一半后才执行自动更新。
还有一点是,应用程序中的XSS等漏洞会将访问令牌暴露给攻击者,因为注入的脚本可以从localStorage
/ sessionStorage
读取,这可能是另一个有利于仅HTTP会话cookie存储的点。
我想在回答第一个问题之前回答第二个问题。
基本上你提到的第三个选项是更新你的访问令牌的最好方法。 访问令牌应该是短暂的(~5分钟),刷新令牌的寿命更长。 当您的访问令牌过期时,将您的刷新令牌发送到后端并获取新的访问令牌。 所以你的回应应该是这样的:
{
"token_type":"bearer",
"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiVlx1MDAxNcKbwoNUwoonbFPCu8KhwrYiLCJpYXQiOjE0NDQyNjI4NjYsImV4cCI6MTQ0NDI2Mjg4Nn0.Dww7TC-d0teDAgsmKHw7bhF2THNichsE6rVJq9xu_2s",
"expires_in":10,
"refresh_token":"7fd15938c823cf58e78019bea2af142f9449696b"
}
所以这个想法是把你的应用程序分离到授权服务器(它生成访问令牌/刷新令牌)和资源服务器(验证访问令牌并访问资源)。 您可以维护模式以根据授权服务器中的访问令牌验证刷新令牌。 请参考这个链接中提到的模式部分,这可能会给你一些想法。 OAuth2用户。 您可以根据需要修改架构。 对于每个请求调用,您不需要将刷新令牌与访问令牌一起发送。 刷新令牌只能发送到授权服务器以生成新的访问令牌。 如何生成刷新令牌? 如果我使用Java,我会使用UUID.randomUUID()
来生成唯一的刷新标记。
现在要回答您的第一个问题,如果您想根据更新的用户记录更新JWT有效内容,则可以使用相同的刷新令牌来生成具有更新的有效内容的新访问令牌。 逻辑保持不变,因为如果用户记录中存在电话号码,它将被添加到有效内容中,否则它将在有效内容中为空。
使用Refresh令牌的主要优点是可以随时使用刷新令牌来更新访问令牌
链接地址: http://www.djcxy.com/p/22027.html上一篇: Handling JWT expiration and JWT payload update
下一篇: JSON Web Token Implementation: access and refresh token