我正在尝试将 Strapi 后端连接到 SvelteKit 前端,并坚持如何保持用户登录状态,以便一切都不会在刷新或导航到新页面时重置。我试过:
- 将 Strapi 发布的 jwt 和用户对象存储在 localStorage 中,并用它初始化 Svelte 存储。看起来我已经接近了,但是 a) 我无法执行
export const user = writable(localStorage.user)
因为该代码正在浏览器中运行,而且我无法将其包装在if (browser) {...}
因为 import 和 export 只能出现在顶层。还尝试了 hooks.js 中的一个函数来读取 localStorage 的内容并更新商店,但似乎从那里调用的函数在服务器上运行,即使它与登录时访问 localStorage 的函数相同......并且加上 b) 从我收集的信息来看,将 jwt 存储在 localStorage 中是不安全的。 - 将 jwt 和用户对象存储在一个仅限 http 的 cookie 中。 Cookies 和 http headers 看起来真的很困惑,我很难操纵它们来存储 jwt 并将其放在每个 header 中。但我认为真正让我难过的是本质上相同的 SSR 问题,即从根本上不知道如何在客户端和服务器之间成功连接。 IE。
if (browser) {...}
似乎从来没有工作过,或者我无法做到这一点。 (如果需要,很高兴提供更多关于我在这里尝试的代码细节。这是一团糟,但它保存在 git 中。)
我知道这是每个有用户的应用程序都需要做的事情,所以我确信 SvelteKit 中有一种方法可以做到这一点。但是我在网上找不到任何解释它的东西,我也无法从官方文档中弄清楚。
所以我错过了一些简单的东西吗? (可能。)或者有什么棘手的方法可以做到这一点?
最佳答案
对于向 Strapi 进行身份验证的 SvelteKit SPA,这是我将使用的快乐路径流程:
- SvelteKit 页面/routes/login.svelte 收集用户名(标识符)和密码,按钮的 on:click 处理程序通过 fetch 将这些值发布到你自己的/routes/auth.js:post( )端点。为什么?因为现在您的服务器端点正在代表用户处理登录,所以您可以在响应中设置一个 httpOnly cookie。
- 在您的 auth.js 端点 post() 方法中,您需要做几件事:
- 使用 fetch 将 identifier 和 password 发布到 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。
- 在登录按钮的最后一部分返回客户端:单击处理程序,从 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/