SvelteKit中Axios拦截器无法访问Cookie问题求助
问题描述
我在使用SvelteKit开发项目时遇到了Cookie相关问题,具体情况如下:
1. 服务端Cookie创建代码(路径:src\routes\api\auth\+server.js)
import {login} from "../../../api/auth.js"; import {loginDTO} from "../../../business/data-transfer-objects/login.js"; import {emptyObject} from "../../../helpers/index.js"; import {errorResponse, successResponse} from "../../../core/response.js"; import {AUTH_TOKEN_KEY} from "../../../core/consts.js"; /** * User Login -> if 200 returned from the server then save the returned token * into a cookie. * @param event * @returns {Promise<Response>} * @constructor */ export async function POST(event) { const data = await event.request.json(); // validate and create DTO. const loginData = loginDTO(data); // if errors returned from building the DTO (validation errors) then return the object. if (loginData?.errors && !emptyObject(loginData.errors)) { return errorResponse(data, loginData.errors, 422) } // perform login. const response = await login(loginData); // if login is not successful then return error. if (response.status !== 200) { // remove password from data. delete data["password"]; return errorResponse(data, response, response.status); } // if login is successful then set the auth cookie. event.cookies.set(AUTH_TOKEN_KEY, response.data.token, { // send cookie for every page path: '/', // server side only cookie so you can't use `document.cookie` httpOnly: false, // only requests from same site can send cookies sameSite: 'strict', // only sent over HTTPS in production secure: process.env.NODE_ENV === 'production', // set cookie to expire after a month maxAge: 60 * 60 * 24 * 30, }) return successResponse(response.data, 200); }
2. 登录表单调用接口的Actions代码
import { redirect } from "@sveltejs/kit"; /** @type {import('./$types').Actions} */ export const actions = { default: async ({request, fetch}) => { const data = Object.fromEntries(await request.formData()); const res = await fetch('api/auth', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(data) }); const response = await res.json() // todo CV-127: once dashboard page is implemented that's the place where this action shall be redirected to. if (response.status == 200) { throw redirect(302, '/') } return response; } }
3. Cookie创建状态
Cookie已成功生成,详情如下:
championship-access-token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlYXQiOiIyMDIzLTA1LTIyVDAxOjI4OjMwLjk0MzAwMTE3MloiLCJpYXQiOjE2ODQ3MTY5MTAsImlkIjo3fQ.VaVfzgnib0DhzRO8jUJ-X_2BRIiAGXIq8eEQOs85anI localhost / 6/20/2023, 8:55:10 PM 192 B ✓ Strict

4. 前端Axios拦截器问题
使用js-cookie库无法获取目标Cookie,也无法创建新Cookie,拦截器代码:
import axios from "axios"; import Cookies from 'js-cookie'; export const app = axios.create({ baseURL: "http://127.0.0.1:8080/api/v1", timeout: 1000, params: {}, }); app.interceptors.request.use( config => { console.log("interceptor -> retrieving cookie:"); Cookies.set("test123", "asdasdasd") console.log(Cookies.get(AUTH_TOKEN_KEY)); console.log("test cookie: ", Cookies.get("test123")) console.log("cookie: ", Cookies.get(AUTH_TOKEN_KEY)); console.log("ALL COOKIES", Cookies.get()) config.headers['Content-Type'] = 'application/json'; return config; }, error => { Promise.reject(error) } );
核心问题
- 明明设置了
httpOnly: false,但Cookie仍被标记为HttpOnly - 前端无法通过
js-cookie访问或创建Cookie
问题分析与解决方案
一、Cookie被标记为HttpOnly的原因及修复
你设置的httpOnly: false未生效,主要有两个可能:
- 后续操作覆盖了Cookie配置:重定向操作或自定义的
successResponse函数可能重新设置了同名Cookie,覆盖了httpOnly属性。 - SvelteKit内置Cookie工具的默认行为干扰:部分场景下
event.cookies.set的配置会被框架默认值覆盖。
修复方法:
直接手动设置响应头,绕过SvelteKit的Cookie工具,确保配置完全生效:
// 替换原来的event.cookies.set代码 const cookieValue = `${AUTH_TOKEN_KEY}=${response.data.token}; Path=/; HttpOnly=false; SameSite=Strict; Max-Age=${60 * 60 * 24 * 30}`; if (process.env.NODE_ENV === 'production') { event.response.headers.append('Set-Cookie', `${cookieValue}; Secure`); } else { event.response.headers.append('Set-Cookie', cookieValue); }
同时检查successResponse函数,确保它没有额外设置同名Cookie。
二、前端无法访问Cookie的原因及修复
前端拿不到Cookie和第一个问题直接相关,还可能受跨域限制影响:
- HttpOnly属性限制:如果Cookie是HttpOnly状态,前端JS(包括
js-cookie)完全无法读取,必须先解决第一步的HttpOnly问题。 - 跨域请求限制:你的Axios请求地址是
http://127.0.0.1:8080,而SvelteKit通常运行在localhost:5173,端口不同属于跨域,会限制Cookie的传递和访问。
修复方法:
1. 确认Cookie的HttpOnly状态
在浏览器开发者工具的Application -> Cookies面板中,查看目标Cookie的HttpOnly选项是否未被勾选。如果仍勾选,回到第一步排查服务端设置。
2. 处理跨域问题
方案A:使用SvelteKit代理请求(推荐)
将Axios的请求地址改为相对路径,通过Vite代理转发到后端,避免跨域:
- 修改Axios配置:
export const app = axios.create({ baseURL: "/api/v1", // 改为相对路径 timeout: 1000, params: {}, }); - 在
vite.config.js中添加代理配置:import { sveltekit } from '@sveltejs/kit/vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [sveltekit()], server: { proxy: { '/api/v1': { target: 'http://127.0.0.1:8080', changeOrigin: true } } } });
方案B:跨域携带Cookie
如果必须直接请求跨域地址,需要同时修改前端和后端配置:
- 前端Axios开启携带凭证:
export const app = axios.create({ baseURL: "http://127.0.0.1:8080/api/v1", timeout: 1000, params: {}, withCredentials: true // 开启该配置 }); - 后端配置CORS:设置响应头
Access-Control-Allow-Credentials: true,且Access-Control-Allow-Origin必须指定你的前端具体地址(不能用*)。
3. 验证js-cookie的使用
确保AUTH_TOKEN_KEY的值和Cookie的名称完全一致(比如championship-access-token),Cookie名称区分大小写。
三、快速验证步骤
- 在浏览器控制台输入
document.cookie,如果能看到目标Cookie,说明HttpOnly设置正确;如果看不到,继续排查服务端配置。 - 检查
Application面板的Cookie列表,确认HttpOnly选项的状态。
内容的提问来源于stack exchange,提问作者MrCujo
相关产品推荐
相关产品推荐

