带有服务器端渲染(SSR)的单页应用程序是优化渲染的流行方法 性能和利用高级缓存策略。

当您需要访问用户时,Supbasse Auth支持服务器端呈现 信息,或者您的服务器需要代表您的 用户来呈现内容。

当用户使用Supabase Auth进行身份验证时 由服务器发布:

1.JWT形式的访问令牌。 2.刷新令牌,它是随机生成的字符串。

大多数Supabase项目的认证服务器都在监听 <project-ref>.supabase.co/auth/v1, 因此访问令牌和刷新令牌是 在上设置为sb-access-tokensb-refresh-tokencookie <project-ref>.supabase.co域。

Web浏览器限制跨域访问cookie,与 同源政策 (SOP).

您的web应用程序无法访问这些cookie, 这些cookie也不会发送到应用程序的服务器。

了解身份验证流程

调用其中一个signIn方法时 浏览器将请求发送到Supabase Auth服务器。 身份验证服务器确定 是否验证电话号码、电子邮件和密码组合、Magic Link, 或者使用社交登录(如果项目中有任何设置)。 成功验证用户身份后,Supabase认证 服务器将用户重定向回单页应用程序。

这些重定向URL具有以下结构:

  https://yourapp.com/...#access_token=<...>&refresh_token=<...>&...
  

成功验证后的第一次访问和刷新令牌是 包含在重定向的URL片段(#符号之后的任何内容)中 地方这是故意的,不可配置。 客户端库被设计为侦听这种类型的URL 访问令牌、刷新令牌以及其中的一些额外信息,最后 将其保存在本地存储中,供库和应用程序进一步使用。

把它放在一起

从身份验证流程可以看出,成功后的初始请求 用户登录后,浏览器登录到应用程序的服务器 包含有关用户的任何信息。 这是因为首先客户端 JavaScript库必须在生成访问和刷新令牌之前运行 可用于您的服务器。

确保在登录后立即重定向路由是非常重要的 无需任何服务器端渲染即可工作。 其他需要授权的路线 不具有相同的限制,前提是发送访问和刷新 令牌发送到服务器。

这通常是通过设置cookie来完成的。这里有一个例子 可以添加到应用程序的根目录:

  supabase.auth.onAuthStateChange((event, session) => {
  if (event === 'SIGNED_OUT' || event === 'USER_DELETED') {
    // delete cookies on sign out
    const expires = new Date(0).toUTCString()
    document.cookie = `my-access-token=; path=/; expires=${expires}; SameSite=Lax; secure`
    document.cookie = `my-refresh-token=; path=/; expires=${expires}; SameSite=Lax; secure`
  } else if (event === 'SIGNED_IN' || event === 'TOKEN_REFRESHED') {
    const maxAge = 100 * 365 * 24 * 60 * 60 // 100 years, never expires
    document.cookie = `my-access-token=${session.access_token}; path=/; max-age=${maxAge}; SameSite=Lax; secure`
    document.cookie = `my-refresh-token=${session.refresh_token}; path=/; max-age=${maxAge}; SameSite=Lax; secure`
  }
})
  

使用标准 document.cookie API在应用程序域的所有路径上设置cookie。 所有后续请求 浏览器对应用程序服务器的设置包括“我的访问令牌”和 `我的刷新令牌cookie(cookie的名称和其他 可以改变参数)。

在服务器端呈现代码中,您现在可以访问用户和会话 信息:

  const refreshToken = req.cookies['my-refresh-token']
const accessToken = req.cookies['my-access-token']

if (refreshToken && accessToken) {
  await supabase.auth.setSession({
    refresh_token: refreshToken,
    access_token: accessToken,
  })
} else {
  // make sure you handle this case!
  throw new Error('User is not authenticated.')
}

// returns user information
await supabase.auth.getUser()
  

使用setSession({ access_token, refresh_token })而不是 setSession(refreshToken)getUser(accessToken)单独作为刷新令牌或访问令牌不能正确标识用户会话。

访问令牌仅在短时间内有效。

即使刷新令牌寿命长,也不能保证用户 具有活动会话。他们可能已注销,而您的应用程序未能 删除我的刷新令牌cookie,或发生其他故障浏览器中的过时刷新令牌。 此外,刷新令牌只能是 第一次使用几秒钟后使用。仅当 访问令牌即将到期,这将避免引入困难诊断应用程序中的注销错误。

一个好的做法是通过延迟渲染页面,而不是在服务器中。一些用户信息是 但包含在访问令牌中,因此在某些情况下,您可能能够使用这些可能过时的信息来呈现页面。

常见问题解答

如何制作CookieHttpOnly

这不是必须的。访问令牌和刷新令牌都设计用于 传递给应用程序中的不同组件。基于浏览器 应用程序的一方需要访问刷新令牌才能正确维护 浏览器会话。

我的服务器收到无效的刷新令牌错误。发生什么事?

从浏览器发送到服务器的刷新令牌很可能是不新鲜的,确保onAuthStateChange侦听器回调没有错误在应用程序的生命周期中相对较早地注册。

当您在服务器端收到此错误时,请尝试延迟 呈现到客户端库可以访问最新刷新令牌并为用户提供更好的体验。

我应该在cookie上设置一个较短的Max Age参数吗?

Max-AgeExpirescookie参数仅控制浏览器将值发送到服务器。由于刷新令牌表示 用户在该浏览器上的长期身份验证会话,设置短 Cookie上的Max-AgeExpires参数只会导致用户体验。

确保用户已注销或会话已结束的唯一方法 是使用getUser()获取用户的详细信息。

我应该为SameSite属性使用什么?

确保您了解物业在不同情况因为某些属性会降低用户体验。

一个好的默认设置是使用Lax,当用户导航到您的网站。Cookie通常需要安全属性, 其仅通过HTTPS发送它们。 然而,当 在localhost上开发。

我可以使用CDN或缓存进行服务器端渲染吗?

是的,但您需要小心至少包含刷新令牌cookie 值。 否则,您可能会意外地使用 属于不同用户的数据!

还要确保设置了正确的缓存控制标头。我们建议无效 每小时或更短时间缓存一次密钥。