如何在SvelteKit中实现路由访问的身份认证校验与跳转?
问题原因
localStorage是浏览器环境专属的API,而SvelteKit中+page.js的load函数默认会在服务器端执行(SSR模式),服务器环境没有localStorage对象,所以会抛出“未定义”的错误。
解决方案
推荐优先用服务器端会话(Cookie)处理登录状态,安全性更高且适配SSR;如果必须依赖客户端存储,也可以强制在浏览器端执行逻辑。
方案一:服务器端Cookie验证(推荐)
将JWT存储在带HttpOnly、Secure标记的Cookie中(避免XSS风险),然后在服务器端代码中读取Cookie并验证登录状态,实现重定向。
1. 单个页面独立处理
在主页和登录页对应的+page.server.js中编写逻辑:
// src/routes/+page.server.js(主页的服务器端逻辑) export async function load({ cookies, redirect }) { const jwt = cookies.get('jwt'); const res = await fetch("[你的认证接口地址]", { headers: jwt ? { Authorization: `Bearer ${jwt}` } : {}, credentials: "include" }); const { logged_in } = await res.json(); if (!logged_in) { throw redirect(302, '/login'); } return { logged_in }; }
// src/routes/login/+page.server.js(登录页的服务器端逻辑) export async function load({ cookies, redirect }) { const jwt = cookies.get('jwt'); const res = await fetch("[你的认证接口地址]", { headers: jwt ? { Authorization: `Bearer ${jwt}` } : {}, credentials: "include" }); const { logged_in } = await res.json(); if (logged_in) { throw redirect(302, '/'); } return { logged_in }; }
2. 全局路由拦截(更高效)
如果需要对所有路由统一处理,用hooks.server.js的handle钩子:
// src/hooks.server.js export async function handle({ event, resolve }) { const jwt = event.cookies.get('jwt'); const res = await fetch("[你的认证接口地址]", { headers: jwt ? { Authorization: `Bearer ${jwt}` } : {}, credentials: "include" }); const { logged_in } = await res.json(); const currentPath = event.url.pathname; // 已登录用户访问/login,重定向到主页 if (currentPath === '/login' && logged_in) { return new Response(null, { status: 302, headers: { Location: '/' } }); } // 未登录用户访问主页,重定向到登录页 if (currentPath === '/' && !logged_in) { return new Response(null, { status: 302, headers: { Location: '/login' } }); } // 其他路由正常处理 return resolve(event); }
方案二:强制客户端执行逻辑(不推荐)
如果必须依赖localStorage,可以关闭当前页面的SSR,让load函数在浏览器端运行:
// src/routes/+page.js 或 src/routes/login/+page.js export const ssr = false; // 关闭SSR,强制在浏览器端执行 export async function load({ url, redirect }) { const jwt = localStorage.getItem('jwt'); const res = await fetch("[你的认证接口地址]", { headers: jwt ? { Authorization: `Bearer ${jwt}` } : {}, credentials: "include" }); const { logged_in } = await res.json(); if (url.pathname === '/' && !logged_in) { throw redirect(302, '/login'); } if (url.pathname === '/login' && logged_in) { throw redirect(302, '/'); } return { logged_in }; }
注意:关闭SSR会导致首屏加载变慢,且
localStorage中的JWT容易被XSS攻击窃取,存在安全隐患,仅在特殊场景下使用。
内容的提问来源于stack exchange,提问作者Basil
相关产品推荐
相关产品推荐

