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

如何使用Svelte与JWT实现无外部提供商的身份认证

纯Svelte+JWT身份认证实现方案(无第三方认证服务商依赖)

以下是完全自主可控、不需要接入任何外部认证平台的实现示例,仅用到Svelte生态和JWT编解码工具:

前置依赖

仅需要安装轻量JWT处理库jose,不需要引入任何认证服务商的SDK:

npm install jose

服务端核心逻辑(基于SvelteKit服务端路由)

1. 登录接口实现(签发JWT)

路径:src/routes/api/login/+server.js

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

// JWT密钥存储在服务端环境变量中,禁止暴露给前端
const JWT_SECRET = new TextEncoder().encode(import.meta.env.VITE_JWT_SECRET);

export async function POST({ request, cookies }) {
  const { username, password } = await request.json();
  // 此处替换为你自己的账号密码校验逻辑,比如查询自建数据库
  const isValidUser = username === 'admin' && password === 'your_password';
  
  if (!isValidUser) {
    return json({ error: '账号或密码错误' }, { status: 401 });
  }

  // 签发有效期24小时的JWT
  const token = await new SignJWT({ username, role: 'user' })
    .setProtectedHeader({ alg: 'HS256' })
    .setIssuedAt()
    .setExpirationTime('24h')
    .sign(JWT_SECRET);

  // 将JWT存入httpOnly Cookie,避免XSS攻击风险
  cookies.set('auth_token', token, {
    path: '/',
    httpOnly: true,
    secure: import.meta.env.PROD,
    sameSite: 'strict',
    maxAge: 60 * 60 * 24
  });

  return json({ success: true });
}

2. 全局JWT校验中间件

路径:src/hooks.server.js

import { jwtVerify } from 'jose';

const JWT_SECRET = new TextEncoder().encode(import.meta.env.VITE_JWT_SECRET);

export async function handle({ event, resolve }) {
  const token = event.cookies.get('auth_token');
  
  if (token) {
    try {
      const { payload } = await jwtVerify(token, JWT_SECRET);
      // 校验通过的用户信息挂载到全局上下文,所有服务端逻辑可直接读取
      event.locals.user = payload;
    } catch (err) {
      // 失效Token直接清除
      event.cookies.delete('auth_token', { path: '/' });
      event.locals.user = null;
    }
  } else {
    event.locals.user = null;
  }

  return resolve(event);
}

前端页面逻辑

1. 登录页实现

路径:src/routes/login/+page.svelte

<script>
  let username = '';
  let password = '';
  let errorMsg = '';

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

    if (res.ok) {
      // 登录成功跳转至受保护页面
      window.location.href = '/dashboard';
    } else {
      const data = await res.json();
      errorMsg = data.error;
    }
  }
</script>

<div class="login-form">
  {#if errorMsg}
    <p class="error-tip">{errorMsg}</p>
  {/if}
  <input bind:value={username} placeholder="请输入用户名" type="text" />
  <input bind:value={password} placeholder="请输入密码" type="password" />
  <button on:click={handleSubmit}>登录</button>
</div>

2. 受保护页面校验

首先在服务端load逻辑中做登录校验,路径:src/routes/dashboard/+page.server.js

export function load({ locals, redirect }) {
  // 未登录用户直接跳转登录页
  if (!locals.user) {
    throw redirect(302, '/login');
  }
  return { user: locals.user };
}

页面中直接使用用户信息:

<script>
  export let data;
</script>

<h1>欢迎登录,{data.user.username}</h1>

登出逻辑

服务端登出接口,路径:src/routes/api/logout/+server.js

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

export async function POST({ cookies }) {
  cookies.delete('auth_token', { path: '/' });
  return json({ success: true });
}

前端调用该接口即可完成登出。

注意事项

  • JWT密钥必须存储在服务端环境变量,绝对不能泄露到前端代码
  • 生产环境必须开启Cookie的secure配置,仅允许HTTPS传输JWT
  • 所有涉及权限的操作,服务端必须再次校验JWT有效性,不能仅依赖前端判断
  • 可根据业务需要新增Refresh Token逻辑,降低JWT过期带来的使用影响

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 11:48:02