【问题标题】:Persisting user state in sveltekit在 sveltekit 中持久化用户状态
【发布时间】:2021-10-17 03:15:57
【问题描述】:

我正在尝试将 Strapi 后端连接到 SvelteKit 前端,并坚持如何保持用户登录状态,以便一切都不会在刷新或导航到新页面时重置。我试过了:

  1. 将 Strapi 发出的 jwt 和用户对象存储在 localStorage 中,并用它初始化 Svelte 存储。好像我已经接近了,但是a)我不能做export const user = writable(localStorage.user),因为该代码正在浏览器中运行,我不能将它包装在if (browser) {...}中,因为导入和导出只能出现在顶层.还尝试了 hooks.js 中的一个函数来读取 localStorage 的内容并更新存储,但似乎从那里调用的函数在服务器上运行,即使它与登录时访问 localStorage 的函数相同......和加上 b) 从我收集的信息来看,将 jwt 存储在 localStorage 中是不安全的。
  2. 将 jwt 和用户对象存储在仅 http 的 cookie 中。 Cookie 和 http 标头似乎真的很混乱,我很难操纵它们来存储 jwt 并将其放入每个标头中。但我认为真正让我难过的是本质上相同的 SSR 问题,即从不知道如何在客户端和服务器之间成功连接。 IE。 if (browser) {...} 似乎从来没有工作过,或者我无法做到,无论如何。 (如果需要,很高兴提供更多关于我在这里尝试过的代码的详细信息。这是一团糟,但它保存在 git 中。)

我知道这是每个拥有用户的应用程序都需要做的事情,所以我确信在 SvelteKit 中有一种方法可以做到这一点。但是我在网上找不到任何解释它的东西,我也无法从官方文档中弄清楚。

所以我错过了一些简单的事情吗? (可能。)或者有什么棘手的方法可以做到这一点?

【问题讨论】:

  • 虽然 Brayden Girard 在此视频youtube.com/watch?v=WgX87HDrAss 中制作了有关将 Strapi 身份验证与 SvelteKit 集成的视频,但他使用 localStorage 来保持状态 - 正如您在上面的 #1 中指出的那样,不推荐使用。

标签: jwt local-storage server-side-rendering httponly sveltekit


【解决方案1】:

对于向 Strapi 进行身份验证的 SvelteKit SPA,这是我将使用的快乐路径流程:

  1. SvelteKit 页面 /routes/login.svelte 收集用户名(标识符)和密码以及按钮的 on:click 处理程序通过 fetch 将这些值发布到 您自己的 /routes/auth.js:post( ) 端点。为什么?因为现在您的服务器端点正在代表用户处理登录,所以您可以在响应中设置一个 httpOnly cookie。
  2. 在您的 auth.js 端点 post() 方法中,您需要做一些事情:
    • 使用 fetch 将 identifierpassword 发布到 Strapi 身份验证 (http://localhost:1337/auth/local) 以获取 JWT (response.body.jwt )
    • 使用 fetch 从 Strapi (http://localhost:1337/users/me) 获取用户信息。在 get 中,添加一个名为 'Authentication' 的标头,其值为 'Bearer' + 您刚刚在上一步中从 Strapi 收到的 JWT
    • 从 Strapi 的响应中返回用户信息,并在 response.body 中将其传递回您的客户端
    • 使用 JWT 的值设置标头 httpOnly cookie。
  3. 在登录按钮的 on:click 处理程序的最后部分返回客户端,从 res.json() 中获取用户信息并将其放入名为 user 的可写存储或 SvelteKit 会话存储中...李>
import { session } from '$app/stores'
...

const loginClickHandler = async () => {
  ...
  const fromEndpoint = await res.json()
  session.set({ user: fromEndpoint.user })
}

此时,您已将用户信息保存在客户端,并将 JWT 作为 httpOnly cookie,客户端 JavaScript 代码无法读取或修改。您对自己服务器的页面或端点发出的每个请求都会发送 JWT cookie。

如果要注销,请调用服务器上的端点 (/auth/logout),将现有 jwt cookie 设置为基于当前日期/时间的过期:

response.headers['Set-Cookie'] = `jwt=; Path=/; HttpOnly; Expires=${new Date().toUTCString()}`

您还想清除存储(或会话存储)中的用户对象。

上述示例的主要内容是您的客户永远不会直接与 Strapi 交谈。 Strapi 的 API 只能由您的 SvelteKit 服务器的端点调用。代表您与 Strapi 的会话的 httpOnly jwt cookie 将包含在对您服务器端点的每个请求中,以使用/验证 Strapi 的 API(或在过期或用户注销时删除)。

还有很多其他方法,但出于安全原因,我更喜欢这种方法。

【讨论】:

  • 我们怎样才能让这个在服务器上也持久化呢?在此示例中,如果我们刷新浏览器,会话将为空,因此我们将被注销。
  • 就我个人而言,我不喜欢使用 JWT 进行身份验证,因为它不可撤销。这是一个更广泛的身份验证示例,其中会话持久保存在服务器上(不是使用 Strapi - 只是一个独立的 SvelteKit 应用程序).​​..github.com/nstuyvesant/sveltekit-auth-example
猜你喜欢
  • 1970-01-01
  • 2011-01-09
  • 1970-01-01
  • 2021-05-20
  • 1970-01-01
  • 1970-01-01
  • 2022-11-07
  • 2012-09-29
  • 2019-08-30
相关资源
最近更新 更多