Authentication 跨多个微服务使用JWT身份验证

Authentication 跨多个微服务使用JWT身份验证,authentication,architecture,jwt,authorization,distributed-system,Authentication,Architecture,Jwt,Authorization,Distributed System,我已经在网上搜索了关于这个问题的答案,但没有什么与我的设置非常相似 因此,我有一个单页应用程序和3项服务: 后端服务-服务A SPA静态文件服务-服务B 身份验证服务-服务C 流程如下: 用户通过访问服务B的/访问站点时,会被重定向到服务B的/login 用户输入凭据并将其发送到服务C以执行身份验证过程并获得用户的权限,这些数据将在JWT中发送 然后,服务B将其放入cookie中,并将其返回到用户的浏览器 然后用户执行一个需要JWT的任务,所以我必须将cookie发送到服务a,但是有一个问题,

我已经在网上搜索了关于这个问题的答案,但没有什么与我的设置非常相似

因此,我有一个单页应用程序和3项服务:

  • 后端服务-服务A
  • SPA静态文件服务-服务B
  • 身份验证服务-服务C
  • 流程如下:

    • 用户通过访问服务B的
      /
      访问站点时,会被重定向到服务B的
      /login
    • 用户输入凭据并将其发送到服务C以执行身份验证过程并获得用户的权限,这些数据将在JWT中发送
    • 然后,服务B将其放入cookie中,并将其返回到用户的浏览器
    • 然后用户执行一个需要JWT的任务,所以我必须将cookie发送到服务a,但是有一个问题,我不能这样做,cookie只用于服务a
    -此链接是我发现的一个源代码的示例,该源代码讨论了将SPA代币存储在何处的问题。 上面说我应该使用cookie来存储JWT,如果:

    • 如果我有自己的后台
    • 如果后端与站点本身位于同一域中
    问题是,我的后端有一个不同的URL,它是一个完全不同的服务,所以使用cookies不是解决方案,或者至少在我看来是这样

    然后它说:

    如果您的单页应用程序具有后端服务器,则应使用授权代码流、带有代码交换验证密钥的授权代码流(PKCE)或混合流在服务器端处理令牌

    这里的问题是,他们甚至没有提到如何以及在哪里存储JWT,以便我可以从多个域访问它

    我还没有找到一种干净的方法来将JWT保存在用户的浏览器上,并将其发送到后端的每个请求中

    我需要的解决方案是在用户的浏览器中以安全的方式保存JWT,允许我将其发送到需要的任何后端服务


    感谢您迄今为止的阅读和帮助

    一种解决方案是在查询参数中使用JWT将请求发送到后端服务


    然后,您可以在后端服务中使用一个中间件,将其转换为
    授权
    头,以便查看它的库继续工作。

    这就是我选择的实现解决方案的方式,但首先需要做一些澄清

    如问题中所述,当浏览器尝试访问站点时,将重定向到/登录路径以验证用户。 但是如果用户不存在,那么我会让用户以最低权限查看该站点。 因此,如果用户已通过身份验证,则带有的cookie将包含带有所需数据的jwt。 如果用户是某种类型的来宾,服务B仍将返回cookie,但将指示用户是来宾

    我选择的实施方式是:

    • 由于上面的解释,我们总是从服务B获得cookie,这意味着我们总是可以告诉我们的站点将cookie保存在浏览器的
      LocalStorage
      中,因此我决定将JWT保存在其中
    • 对于我向服务A发出的每个提取请求,我将设置一个名为
      Authorization
      的头,使其值为
      Bearer
      (在
      中插入jwt),如本文关于授权的说明所述
    关于安全:

    因此,由于无法将JWT保存在与服务a相关的cookie中(服务B和a来自不同的域),因此我们只剩下
    LocalStorage
    选项。 LocalStorage不是最安全的方式,默认情况下易受XSS攻击, 但是,正如mikejones1477在回答中所说,现代浏览器对XSS有很强的防御能力,并且本地存储不易受到CSRF的攻击。
    因此,本质上,应该特别注意XSS攻击,但这是在不同域的服务之间传递令牌的方式。

    当我从服务B接收JWT到用户浏览器时,它仍然无法解决在何处保存JWT的问题。如果所有服务都在同一域中,您可以将其存储在cookie或服务B的本地存储中。这一点在这里也适用。但问题是我不希望它们位于同一来源,我希望它们能够独立扩展。我想说的是,让服务B将JWT放在本地存储中,当它想向服务a发送请求时,从本地存储中提取它,并将其作为查询参数添加到服务a的请求中。查询参数不受cookie或本地存储的限制。另外,我说的是“领域”,而不是“起源”。如果您进行了扩展,这意味着您已经有了http代理,如果您有了http代理,您不需要单独的域,您可以在代理上执行重定向。