Web前端入门第 82 问:JavaScript cookie 有大小限制吗?溢出会怎样?
面试时候经常会被问及 Cookie 大小限制,但一直没尝试写一些 demo 测试下溢出极限值会怎样~~
本文就来看看各种极限情况!
英文
测试代码:
(() => { const maxSize = 4 * 1024; // 4KB const name = 'name' // 最大出入的 value 长度 const maxValueStr = 'a'.repeat(maxSize - name.length); // firefox 不能使用 Secure document.cookie = `${name}=${encodeURIComponent(maxValueStr)};expires=${new Date(2026, 0, 1).toUTCString()};path=/`; })()
Chrome/Edge/Firefox 浏览器
英文:
名字 + 内容
字符串长度限制 4096 字符。 各家浏览器的存储面板都能看到 Cookie 大小,此大小包含存入 Cookie 的
名字和内容加在一起的长度
。不同之处
Chrome/Edge
超过 4KB 大小无法存储,浏览器无报错,也无提示,纯粹毫无感知。
Firefox
超过 4KB 大小会有提示:
Cookie “name”太大而无效。最大大小为 4096 字节。
比如这段代码存入 cookie 的值超过一个字符:
(() => { const maxSize = 4 * 1024 - 5; // 4KB const maxStr = 'a'.repeat(maxSize) + 'b1'; console.log('🚀 ~ maxStr:', maxStr.length); document.cookie = `name=${encodeURIComponent(maxStr)};expires=${new Date(2026, 0, 1).toUTCString()};path=/`; })()
运行有警告:
如果在 Firefox 中 localhost 使用 secure 会报错!!
由于非 HTTPS Cookie 无法设置“secure”属性,已拒绝 Cookie “name”。
比如这段代码在本地 localhost 的环境中 Chrome 和 Edge 都能正常运行,但是 Firefox 会报错:
document.cookie = `name=${encodeURIComponent(maxStr)};expires=${new Date(2026, 0, 1).toUTCString()};path=/;Secure;SameSite=Lax`;
报错:
中文
一个中文占用3个英文长度!!!
测试代码:
(() => { const maxSize = 4 * 1024; // 4KB const name = 'name' const valueSize = maxSize - name.length console.log(valueSize / 3); const value = '中'.repeat(Math.floor(valueSize / 3)); // firefox 不能使用 Secure document.cookie = `name=${(value)};expires=${new Date(2026, 0, 1).toUTCString()};path=/`; })()
4KB 字符串长度减去 name 的长度,除以 3 等于 1364 中文字符长度,刚好是浏览器能存储的极限值。
Firefox 显示的大小比较另类,它没按照转换后的大小显示,而是直接显示了中文值长度 + 英文名称长度,而 Chrome 和 Edge 显示的是占用空间长度。如下图:
一般在存储中文的的时候,会用到 encodeURIComponent
编码一下中文字符,这方法编码之后,一个中文字符将会转成 9 个英文字符,使用这种方法存储中文时候需特别注意!!!
使用 cookieStore
cookieStore 存入超过大小限制的字符串长度时,会报一个奇奇怪怪的错误,比如:
(async () => { const maxSize = 4 * 1024; // 4KB const name = 'name' const valueSize = maxSize - name.length console.log(valueSize / 3); const value = '中'.repeat(Math.floor(valueSize / 3)); const res = await cookieStore.set({ name: 'name', // 比极限值多出一个长度 value: value + '1', expires: new Date(2026, 0, 1).getTime(), // Unix 时间戳(以毫秒为单位表示) path: '/', sameSite: 'lax' }) console.log('存储结果:', res); // 正常写入返回 undefined })()
报错:
翻译过来的大致意思:
由于解析时出现问题,导致 Cookie 格式错误,无法存储。
反正不是明确的告诉开发者长度异常了!!所以在使用 cookieStore
时,需要进行异常捕获。
本文编写时 Firefox 最新版本 138.0.4 还不支持 cookieStore。
Cookie 个数限制
单个 Cookie 的大小限制了解了,再看看 Cookie 个数限制。
多个超大 Cookie
测试代码:
(async () => { document.cookie = '' const name = 'name' // 最大出入的 value 长度 let cookieStr = '' for (let i = 0; i < 200; i++) { document.cookie = `${name + i}=${'a'.repeat(4000)};expires=${new Date(2026, 0, 1).toUTCString()};path=/`; } // JS 查找 name 出现次数 console.log(document.cookie.match(/name/g).length) })()
第一次都能正常打开页面,第二次刷新页面之后都会报错:
此问题应该是跟 http 协议的限制有关,请求头发送的 Cookie 长度太长了,导致响应 431 状态码。
Firefox 在页面未正常打卡的情况下还不支持清空 Cookie,需要点击
右上角菜单--设置--隐私与安全--清除数据
删除保存的超大 Cookie 浏览器才能正常访问。小 Cookie 个数限制
测试代码:
(async () => { function setCookie(name, value) { return new Promise((resolve, reject) => { setTimeout(() => { document.cookie = `${name}=${value};path=/`; resolve() }, 5); }); } const name = 'name' // 最大出入的 value 长度 let cookieStr = '' for (let i = 0; i < 2000; i++) { console.log('正在写入:', i); await setCookie(name + i, 'a') } setTimeout(() => { // JS 查找 name 出现次数 console.log(document.cookie?.match(/name/g)?.length) }, 1000); })()
Chrome、Edge、Firefox 浏览器每次刷新写入的 Cookie 个数都不一样,可以复制以上代码在浏览器中测试!
AI 回答:
写在最后
根据测试结果可以得出:在使用 Cookie 时只建议用于存入关键数据,而不是用来做相关缓存!!
文章首发于微信公众号【前端路引】,欢迎 微信扫一扫 查看更多文章。
本文来自博客园,作者:前端路引,转载请注明原文链接:https://www.cnblogs.com/linx/p/19010392
评论