首页 文章

JWT身份验证和刷新令牌实现

提问于
浏览
7

我正在开发一个具有自己的身份验证和授权机制的REST应用程序 . 我想使用JSON Web Tokens进行身份验证 . 以下是有效且安全的实施吗?

  • 将开发REST API以接受用户名和密码并进行身份验证 . 要使用的HTTP方法是POST,因此没有缓存 . 此外,在运输时将有SSL用于安全性

  • 在身份验证时,将创建两个JWT - 访问令牌和刷新令牌 . 刷新令牌的有效期将更长 . 这两个令牌都将用cookie编写,以便在每个后续请求中发送

  • 在每次REST API调用中,将从HTTP标头中检索标记 . 如果访问令牌未过期,请检查用户的权限并允许相应的访问权限 . 如果访问令牌已过期但刷新令牌有效,请重新创建新访问令牌并刷新具有新到期日期的令牌(执行所有必要的检查以确保用户的身份验证权限未被撤销)并通过Cookies发回

  • 提供将重置cookie的注销REST API,因此在完成登录之前将拒绝后续API调用 .

我对刷新令牌的理解是:

由于存在刷新令牌,我们可以缩短访问令牌的有效期,并经常(在访问令牌到期时)检查用户是否仍有权登录 .

如果我错了,请纠正我 .

2 回答

  • 1

    将开发REST API以接受用户名和密码并进行身份验证 . 要使用的HTTP方法是POST,因此没有缓存 . 此外,在运输时将有SSL用于安全性

    大多数人都这样做,所以你在这里很好 .

    在身份验证时,将创建两个JWT - 访问令牌和刷新令牌 . 刷新令牌的有效期将更长 . 这两个令牌都将用cookie编写,以便在每个后续请求中发送

    将令牌存储在cookie中我自己并不危险,但是如果你以某种方式在服务器上获取JWT模块从那里读取它们你很容易受到CSRF攻击,任何网页都可以触发用户浏览器向你的网站发送表单cookie服务器,除非您使用CSRF令牌 . 因此,通常它们存储在localStorage中,并且每次都“手动”添加到请求标头中 .

    在每个REST API调用中,将从HTTP标头中检索标记 . 如果访问令牌未过期,请检查用户的权限并允许相应的访问权限 . 如果访问令牌已过期但刷新令牌有效,请重新创建新访问令牌并刷新具有新到期日期的令牌(执行所有必要的检查以确保用户的身份验证权限未被撤销)并通过Cookies发回

    除了 Cookies 危险之外,它似乎是安全的 .

    提供将重置cookie的注销REST API,因此在登录完成之前将拒绝后续API调用 .

    您甚至不需要进行API调用,只需清除cookie或localStorage对象,并确保客户端不会丢失令牌 .

    express-jwt模块的标准要求令牌位于其自己的"Authorization: Bearer [Token]"标头中,我强烈推荐使用cookie . localStorage API可以一直回到IE8,所以你应该很好 .

    Edit:

    首先,了解XSS和CSRF攻击之间的区别非常重要,因为它们通常被认为是相同的 .

    XSS是用户在其他用户浏览器中运行您的域时不安全的JS,当发生这种情况时,localStorage中的JWT或cookie中的会话和JWT都不安全 . 使用cookies上的httpOnly标志,您无法直接访问它们,但浏览器仍会向您的服务器发送带有AJAX请求的浏览器 . 如果发生这种情况,你通常会运气不好 . 要防止这种情况发生,请确保在发送到浏览器时转义所有用户输入 .

    如果您使用脚本标签或iframe加载第三方JS,这可能会损害localStorage,除非您小心,但我没有足够的工作来帮助您 .

    CSRF仅在其他域尝试通过让浏览器自动发送cookie时将正常HTML表单发送到您的服务器时 . 框架通过将唯一的随机字符串作为隐藏字段插入并在提交时再次检查它来防止这种情况 . JWT在localStorage中是安全的,因为每个域都有自己独立的localStorage区域 .

    但最终所有这些取决于您的服务是否将使用单个域,在这种情况下,httpOnly cookie将是足够安全且更容易设置,但如果您想在多个域上传播您的服务,如api.domain.com应用程序 . domain.com或添加一个本机应用程序,你被迫将你的JWT存储在localStorage或其他一些本机存储区域 .

    希望这可以帮助!

  • 5

    我对刷新令牌的理解是:由于存在刷新令牌,我们可以缩短访问令牌的有效期,并经常检查(在访问令牌到期时)用户仍然有权登录 . 如果我错了,请纠正我 .

    假设您正在谈论在OAuth中使用JWT作为承载令牌(我强烈建议遵循OAuth 2.0协议),那是对的 .

    通过JWT中额外的身份验证时间(身份验证时间戳)声明,您甚至可以删除第二个令牌并将您的访问权限作为刷新令牌发送(如果令牌有效,则身份验证服务器可以发出新的访问令牌&auth-time在允许的范围内)...但是当然,遵循标准也是好的;)

    无论如何,在使用JWT作为刷新令牌之前,你应该考虑一些额外的方面(往往会变得困难或甚至违背JWT的基本思想),因为这基本上意味着你引入了长寿命的JWT:

    • 您是否需要按主题强制用户注销/令牌撤销(例如,如果用户被识别为欺诈)?

    • 您是否需要撤销特定令牌(例如,如果用户丢失设备)?

    • ......

    根据您的使用情况,您应该考虑所有可能的影响,长期生命令牌,因为他们通常要求您在服务器端引入某种状态(例如,允许撤销/黑名单) . 请记住,JWT概念的美感和安全性在JWT中是短暂的 .

相关问题