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

Svelte:如何将命名动作返回的Bearer令牌存入localStorage?

解决方案:在SvelteKit中获取登录令牌并存入localStorage

针对你的需求,有两种实用方案,可根据你想要的页面行为选择:

方案一:保留传统表单提交(页面刷新),从动作返回值中存令牌

利用SvelteKit命名动作的返回值,在页面加载时读取并写入localStorage:

  1. 修改+page.server.js的命名动作,返回获取到的令牌:
export const actions = {
  login: async ({ request }) => {
    const formData = await request.formData();
    const username = formData.get('username');
    const password = formData.get('password');

    // 调用外部Web API获取令牌(你的原有逻辑)
    const apiRes = await fetch('https://你的API地址/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ username, password })
    });
    const authData = await apiRes.json();

    // 返回令牌,同时可保留原有写Cookie的逻辑
    return {
      success: true,
      token: authData.token
    };
  }
};
  1. 在+page.svelte中处理返回值,页面加载时检查动作返回的令牌并存入localStorage:
<script>
  import { page } from '$app/stores';
  import { onMount } from 'svelte';

  onMount(() => {
    // 读取动作提交后返回的form数据
    const loginResult = $page.form;
    if (loginResult?.success && loginResult.token) {
      // 存入localStorage
      localStorage.setItem('auth_token', loginResult.token);
      // 重定向到首页或其他页面,避免刷新后重复存储
      window.location.href = '/';
    }
  });
</script>

<form method="POST" action="?/login">
  <input type="text" name="username" placeholder="用户名" required />
  <input type="password" name="password" placeholder="密码" required />
  <button type="submit">登录</button>
</form>

方案二:改用API路由实现无刷新登录(推荐)

通过创建SvelteKit的API路由,前端用fetch调用(服务器端转发请求避免跨域),直接拿到令牌存入localStorage,体验更流畅:

  1. 创建API路由文件src/routes/api/login/+server.js:
export async function POST({ request }) {
  const { username, password } = await request.json();

  // 服务器端调用外部API,不受浏览器同源策略限制
  const apiRes = await fetch('https://你的API地址/login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username, password })
  });

  if (!apiRes.ok) {
    return new Response(JSON.stringify({ error: '登录失败' }), { status: 401 });
  }

  const authData = await apiRes.json();
  // 返回令牌,也可在此设置Cookie
  return new Response(JSON.stringify({ token: authData.token }), {
    headers: { 'Content-Type': 'application/json' }
  });
}
  1. 在+page.svelte中用fetch调用API:
<script>
  let username = '';
  let password = '';
  let errorMsg = '';

  async function handleLogin(e) {
    e.preventDefault();
    errorMsg = '';

    try {
      const res = await fetch('/api/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ username, password })
      });

      if (!res.ok) {
        const errData = await res.json();
        errorMsg = errData.error || '登录失败';
        return;
      }

      const { token } = await res.json();
      localStorage.setItem('auth_token', token);
      // 登录成功后跳转
      window.location.href = '/';
    } catch (err) {
      errorMsg = '网络异常,请稍后重试';
    }
  }
</script>

<form on:submit={handleLogin}>
  <input type="text" bind:value={username} placeholder="用户名" required />
  <input type="password" bind:value={password} placeholder="密码" required />
  <button type="submit">登录</button>
  {#if errorMsg}
    <p style="color: #dc2626;">{errorMsg}</p>
  {/if}
</form>

关键说明

  • 你之前前端fetch跨域是因为浏览器的同源策略,但服务器端(+page.server.js或+server.js)调用外部API不受此限制,所以两种方案都能解决跨域问题。
  • 方案二更符合现代单页应用的体验,无页面刷新;方案一适合需要保留传统表单提交行为的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 18:33:11