Firebase身份验证状态在客户端上持续存在,但不会在硬刷新时持续存在

Jon*_*Jon 3 firebase firebase-security reactjs isomorphic-javascript firebase-authentication

我正在构建一个使用Express来处理服务器请求的同构React应用程序.

在客户端运行捆绑的React应用程序时,我的Firebase登录流程运行良好:

  • 我使用Firebase的电子邮件/密码选项登录
  • 验证后,ref.getAuth()成功返回用户的auth对象
  • ref.getAuth()在我的应用程序客户端(通过react-router)导航时的后续调用也会返回一个成功的auth对象.

但是,即使在客户端成功登录后,硬刷新(来自服务器)也不会持续存在.在服务器上下文中使用相同的React组件,ref.getAuth()返回null.

我是否错过了在服务器上以与在客户端上工作相同的方式进行此工作的步骤(用例是网站的硬刷新)?

Mic*_*ley 8

如果您在服务器上连接到Firebase作为同构/通用渲染的一部分(我假设您是这样),Firebase无法知道哪个用户向您的服务器发起了请求,然后随后向Firebase-on发出了请求在客户端,用户的cookie可以一起发送到Firebase,但是在服务器上发起请求的是您的服务器,而不是客户端,因此不与任何给定用户相关联.

我的第一个想法是,为了从服务器发送身份验证,您需要在自己的服务器上进行某种登录; 一旦您验证(使用Firebase或其他方式)用户是他们所说的用户,您就可以生成一个令牌,您可以(安全地)保存在用户的会话中并发送回客户端.然后,在客户端上,每个服务器的请求,就在渲染你的应用程序做出反应用React.render*,你会调用authWithCustomToken()与该用户的令牌.

但需要注意的是,对Firebase数据库的身份验证是全局的 - 当您对Firebase引用进行身份验证时(即使在Node.js中),指向同一数据库的每个其他ref都会使用这些凭据进行身份验证; 您无法使用单独的引用以不同用户身份登录.因此,如果服务器上的React渲染管道在调用auth回调和呈现应用程序之间进行任何异步操作(例如,如果您使用react-async之类的东西或在渲染之前执行其他奇特的异步数据加载),那么用户根据您的Firebase进行身份验证可能会在您渲染应用程序时发生更改.但是,如果您的渲染管道纯粹是同步的,那么您应该能够摆脱这种策略(getAuth() 可以帮助确保您在渲染之前拥有正确的身份验证).

除此之外,我认为最直接的解决方案如下:

  1. 通过您自己的服务器验证您的用户,创建安全令牌并将其传递回客户端以进行身份​​验证.将此令牌存储在用户的会话中,以便客户端可以请求它并在必要时在客户端上使用它进行身份验证.您还需要生成自己的auth数据(通常传递给回调的东西authWithPassword)并将其存储在会话中.

  2. 对于Firebase的服务器请求,请使用以下推荐的服务器身份验证方案之一:

    使用Firebase应用程序密钥:所有身份验证方法都可以接受Firebase应用程序密钥而不是JWT令牌.这将授予服务器对整个F​​irebase数据库的完全读写权限.除非通过App Dashboard撤消,否则此访问权限永不过期.

    使用安全JWT并将可选admin声明设置为true:此方法将授予服务器对整个F​​irebase数据库的完全读写访问权限.此令牌将正常到期,因此相应地设置到期时间非常重要.

    使用安全的JWT设计只能访问服务器需要访问的数据:这种方法更复杂,但它是验证服务器最安全的方法,因为它使安全和Firebase规则阻止服务器做任何事情它不应该,即使它在某种程度上受到损害.

  3. 包括服务器逻辑以确保当前登录的用户只能访问适当的数据.由于上述身份验证方法将授予用户访问或不访问的数据访问权限,因此您需要采取自己的步骤,以确保用户不会意外访问他们不应该访问的内容.

  4. 将您在步骤1中存储在会话中的身份验证数据作为属性传递给React应用程序,而不是依赖于ref.getAuth()在React应用程序中获取此数据(因为它无法在服务器上运行),以识别UI中的用户.