You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SvelteKit中安全存储JWT并实现登录态持久化?

符合SvelteKit规范的JWT安全存储与持久化登录实现方案

核心原则:敏感的JWT凭证绝对不要存储在客户端localStorage或者JS可读写的普通cookie中,通过SvelteKit服务端设置带HttpOnly、Secure、SameSite安全属性的cookie是官方推荐的最安全方案,同时天然支持用户重启浏览器后保持登录状态。


第一步:新增服务端登录API路由

将原来客户端直接调用后端登录接口的逻辑移到SvelteKit服务端处理,由服务端负责接收token并设置cookie。
新建文件src/routes/api/login/+server.js,代码如下:

import { json } from '@sveltejs/kit';

export async function POST({ request, cookies }) {
  const { username, password } = await request.json();
  // 调用你的后端登录接口获取token,替换为实际的后端接口地址
  const backendResponse = await fetch('后端登录接口地址', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username, password })
  });
  const result = await backendResponse.json();

  if (backendResponse.ok && result.token?.access_token) {
    // 服务端设置安全cookie,属性配置可以根据需求调整
    cookies.set('access_token', result.token.access_token, {
      path: '/',
      httpOnly: true, // 禁止客户端JS读取,彻底避免XSS攻击窃取token
      secure: process.env.NODE_ENV === 'production', // 生产环境仅在HTTPS下传输
      sameSite: 'strict', // 避免CSRF攻击
      maxAge: 60 * 60 * 24 * 7 // cookie有效期7天,对应保持登录的时长
    });
    return json({ success: true });
  } else {
    return json({ success: false, message: result.message || '登录失败' }, { status: 400 });
  }
}

第二步:修改客户端登录页的提交逻辑

把原来直接调用后端接口的逻辑替换为调用自己的服务端API路由,调整submit函数:

async function submit(event) {
  errors = null;
  try {
    const res = await fetch('/api/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ username, password })
    });
    const data = await res.json();
    if (res.ok) {
      goto('/profile');
    } else {
      message = data.message;
      hasError = true;
      setTimeout(() => { hasError = false }, 5000);
    }
  } catch (e) {
    message = '网络异常,请稍后重试';
    hasError = true;
    setTimeout(() => { hasError = false }, 5000);
  }
}

第三步:实现持久化登录状态校验

通过SvelteKit的服务端钩子统一读取cookie,初始化登录状态,新建文件src/hooks.server.js:

export async function handle({ event, resolve }) {
  const accessToken = event.cookies.get('access_token');
  if (accessToken) {
    // 可在此处添加token有效性校验逻辑:比如请求后端验签、或者本地解析JWT获取用户信息
    event.locals.user = { isLoggedIn: true /* 可补充解析后的用户ID、用户名等信息 */ };
  } else {
    event.locals.user = null;
  }
  return resolve(event);
}

调整你原有页面的load函数,直接从服务端上下文读取登录状态即可:

export async function load({ locals }) {
  if (locals.user) {
    return {
      status: 302,
      redirect: '/'
    };
  }
  return {};
}

第四步:接口请求带token的处理

所有需要携带JWT请求后端的场景,都统一走SvelteKit服务端API路由转发,由服务端从cookie读取token添加到请求头,避免token暴露到客户端:
示例:获取用户信息的服务端API路由src/routes/api/profile/+server.js

import { json } from '@sveltejs/kit';

export async function GET({ cookies }) {
  const accessToken = cookies.get('access_token');
  if (!accessToken) return json({ error: '未登录' }, { status: 401 });
  // 调用后端接口,携带token
  const backendRes = await fetch('后端用户信息接口地址', {
    headers: { 'Authorization': `Bearer ${accessToken}` }
  });
  return json(await backendRes.json());
}

补充:退出登录实现

只需新增一个服务端API路由,删除对应cookie即可:

// src/routes/api/logout/+server.js
import { json } from '@sveltejs/kit';
export async function POST({ cookies }) {
  cookies.delete('access_token', { path: '/' });
  return json({ success: true });
}

内容的提问来源于stack exchange,提问作者Kodoxa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 12:45:06