如何使用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
相关产品推荐
相关产品推荐

