jwt - 在 sveltekit 中持久化用户状态

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

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

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

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

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

最佳答案

对于向 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”的 header ,其值为“Bearer”+ 您在上一步中刚刚从 Strapi 收到的 JWT
    • 从 Strapi 的响应中返回用户信息,并在 response.body 中将其传回给您的客户端
    • 使用 JWT 的值设置 header httpOnly cookie。
  3. 在登录按钮的最后一部分返回客户端:单击处理程序,从 res.json() 中获取用户信息并将其放入名为 user 的可写存储或 SvelteKit session 存储中...<
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()}`

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

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

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

关于jwt - 在 sveltekit 中持久化用户状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68779637/

相关文章:

json - 如何在JWT Header中设置JWT类型

Angular 6 样板仅具有基本功能(始终需要)?

python - 如何在 python 中使用 RSA SHA-256 签署 token ?

javascript - 刷新前存储元素中的数据

复选框上的 Javascript 克隆此 div,未选中时删除此 div

javascript - Vue.js 服务端渲染中的组件

http-headers - 无法获取标题 AUTHORIZATION 但更改为 AUTHORIZATION 可以获得值

javascript - IE11 不接受字符串(变量)作为 localStorage.setItem() 的参数

ruby-on-rails - 在 Node.js(纯 V8 环境)中加载 webpack-dev-server Assets

javascript - 使用 next.js 进行服务器端渲染与传统 SSR