SvelteKit中如何通过Auth.js将JWT传递至+page.server.js
SvelteKit + Auth.js 认证流程:JWT传递与用户数据查询问题
问题背景
刚接触SvelteKit和认证开发,用Auth.js实现GitHub登录,期望流程是:
用户登录→SvelteKitAuth返回含用户ID的JWT→访问/dashboard→+page.server.js通过JWT中的ID查询数据库→展示用户数据。
目前已成功生成包含用户ID的JWT,但不清楚如何将JWT传递到+page.server.js和+page.svelte。尝试了从cookie读取token并存入event.locals的方案,但不确定该方案是否合理,也疑惑是否应该从cookie读取token。
当前代码
认证中间件与Auth配置
async function authorization({ event, resolve }) { if (event.url.pathname.startsWith('/article')) { const token = event.cookies.get('next-auth.session-token'); const decoded = await decode({ token, secret: SVELTEAUTH_SECRET }); console.log(decoded); if (!token) { throw redirect(303, '/auth?redirectSource=articleView'); } } return resolve(event); } export const handle = sequence( SvelteKitAuth({ providers: [GitHub({ clientId: GITHUB_ID, clientSecret: GITHUB_SECRET })], jwt: true, secret: SVELTEAUTH_SECRET, session: { strategy: 'jwt' }, callbacks: { async jwt({ token, account, profile }) { if (account) { token.userId = profile.id; } return token; } } }), authorization );
解码后的JWT内容
{ "name": "zerakot", "email": "********", "picture": "https://avatars.githubusercontent.com/u/49678485?v=4", "sub": "49678485", "userId": 49678485, "iat": 1695501797, "exp": 1698093797, "jti": "48a73079-bcba-46e4-851e-df5e7a43f089" }
找到的解决方案代码
async function authorization({ event, resolve }) { if (event.url.pathname.startsWith('/article')) { const token = event.cookies.get('next-auth.session-token'); if (!token) { throw redirect(303, '/auth?redirectSource=articleView'); } event.locals.token = token; } return resolve(event); }
解答与优化方案
1. 从cookie读取token是合理且安全的
Auth.js使用JWT会话策略时,默认会将JWT存储在next-auth.session-token这个HttpOnly Cookie中。HttpOnly属性能阻止前端JavaScript访问该Cookie,有效防范XSS攻击窃取token,这是Auth.js官方推荐的服务端获取token的方式,完全符合安全规范。
2. 优化中间件:直接存储解码后的用户信息
不用把完整token存入event.locals,而是解码后提取需要的用户ID(或其他信息)存入,减少后续页面的重复解码操作,同时避免不必要的token暴露:
import { decode } from '@auth/core/jwt'; import { SVELTEAUTH_SECRET } from '$env/static/private'; import { redirect } from '@sveltejs/kit'; async function authorization({ event, resolve }) { // 统一管理需要认证的路径 const protectedPaths = ['/article', '/dashboard']; if (protectedPaths.some(path => event.url.pathname.startsWith(path))) { const token = event.cookies.get('next-auth.session-token'); if (!token) { // 跳转时保留原路径,登录后可返回 throw redirect(303, `/auth?redirectSource=${encodeURIComponent(event.url.pathname)}`); } try { const decoded = await decode({ token, secret: SVELTEAUTH_SECRET }); // 将用户ID存入locals,供后续页面直接使用 event.locals.userId = decoded.userId; // 若需要完整用户信息,也可存入 // event.locals.user = decoded; } catch (error) { // token过期或篡改时,强制跳转登录 throw redirect(303, `/auth?redirectSource=${encodeURIComponent(event.url.pathname)}`); } } return resolve(event); }
3. 在+page.server.js中使用用户ID查询数据
现在在/dashboard/+page.server.js里可以直接从event.locals获取userId,无需重复处理cookie:
import { db } from '$lib/database'; // 替换为你的数据库连接 import { redirect } from '@sveltejs/kit'; export async function load({ locals }) { if (!locals.userId) { throw redirect(303, '/auth?redirectSource=/dashboard'); } // 根据userId查询数据库 const userData = await db.user.findUnique({ where: { id: locals.userId } }); return { userData }; }
4. 在+page.svelte中展示数据
直接通过load函数返回的data对象获取用户数据:
<script> export let data; </script> <div class="dashboard"> <h1>用户仪表盘</h1> <p>用户ID: {data.userData.id}</p> <p>用户名: {data.userData.name}</p> <!-- 其他需要展示的用户信息 --> </div>
5. 额外优化建议
- 调整JWT过期时间:Auth.js默认JWT有效期为30天,可根据需求在SvelteKitAuth配置中修改:
SvelteKitAuth({ // ...其他配置 session: { strategy: 'jwt', maxAge: 24 * 60 * 60, // 设置为1天,按需调整 }, })
- 前端无需接触JWT:HttpOnly Cookie已经确保token不会被前端获取,前端只需要使用服务端返回的用户数据即可,避免不必要的安全风险。
内容的提问来源于stack exchange,提问作者zerakot
相关产品推荐
相关产品推荐

