化耀 發表於 2025-7-29 10:54:00

Web前端入门第 82 问:JavaScript cookie 有大小限制吗?溢出会怎样?

<p>面试时候经常会被问及 Cookie 大小限制,但一直没尝试写一些 demo 测试下溢出极限值会怎样~~</p>
<p>本文就来看看各种极限情况!</p>
<h2 id="英文">英文</h2>
<p>测试代码:</p>
<pre><code class="language-js">(() =&gt; {
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=/`;
})()
</code></pre>
<h3 id="chromeedgefirefox-浏览器">Chrome/Edge/Firefox 浏览器</h3>
<p><strong>英文:</strong><code>名字 + 内容</code> 字符串长度限制 4096 字符。</p>
<p><img src="https://img2024.cnblogs.com/blog/596097/202507/596097-20250729105254488-63108974.png"></p>
<p>各家浏览器的存储面板都能看到 Cookie 大小,此大小包含存入 Cookie 的<strong>名字和内容加在一起的长度</strong>。</p>
<h3 id="不同之处">不同之处</h3>
<h4 id="chromeedge">Chrome/Edge</h4>
<p>超过 4KB 大小无法存储,浏览器无报错,也无提示,纯粹毫无感知。</p>
<h4 id="firefox">Firefox</h4>
<p>超过 4KB 大小会有提示:</p>
<pre><code class="language-bash">Cookie “name”太大而无效。最大大小为 4096 字节。
</code></pre>
<p>比如这段代码存入 cookie 的值超过一个字符:</p>
<pre><code class="language-js">(() =&gt; {
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=/`;
})()
</code></pre>
<p>运行有警告:</p>
<p><img src="https://img2024.cnblogs.com/blog/596097/202507/596097-20250729105300383-1792381640.png"></p>
<p>如果在 Firefox 中 localhost 使用 secure 会报错!!</p>
<pre><code class="language-bash">由于非 HTTPS Cookie 无法设置“secure”属性,已拒绝 Cookie “name”。
</code></pre>
<p>比如这段代码在本地 localhost 的环境中 Chrome 和 Edge 都能正常运行,但是 Firefox 会报错:</p>
<pre><code class="language-js">document.cookie = `name=${encodeURIComponent(maxStr)};expires=${new Date(2026, 0, 1).toUTCString()};path=/;Secure;SameSite=Lax`;
</code></pre>
<p>报错:</p>
<p><img src="https://img2024.cnblogs.com/blog/596097/202507/596097-20250729105305290-2076321132.png"></p>
<h2 id="中文">中文</h2>
<p><strong>一个中文占用3个英文长度!!!</strong></p>
<p>测试代码:</p>
<pre><code class="language-js">(() =&gt; {
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=/`;
})()
</code></pre>
<p>4KB 字符串长度减去 name 的长度,除以 3 等于 1364 中文字符长度,刚好是浏览器能存储的极限值。</p>
<p>Firefox 显示的大小比较另类,它没按照转换后的大小显示,而是直接显示了中文值长度 + 英文名称长度,而 Chrome 和 Edge 显示的是占用空间长度。如下图:</p>
<p><img src="https://img2024.cnblogs.com/blog/596097/202507/596097-20250729105311730-649095399.png"></p>
<p>一般在存储中文的的时候,会用到 <code>encodeURIComponent</code> 编码一下中文字符,这方法编码之后,一个中文字符将会转成 9 个英文字符,使用这种方法存储中文时候需特别注意!!!</p>
<p><img src="https://img2024.cnblogs.com/blog/596097/202507/596097-20250729105319539-1528176271.png"></p>
<h2 id="使用-cookiestore">使用 cookieStore</h2>
<p>cookieStore 存入超过大小限制的字符串长度时,会报一个奇奇怪怪的错误,比如:</p>
<pre><code class="language-js">(async () =&gt; {
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
})()
</code></pre>
<p>报错:</p>
<p><img src="https://img2024.cnblogs.com/blog/596097/202507/596097-20250729105333135-450207816.png"></p>
<p>翻译过来的大致意思:<strong>由于解析时出现问题,导致 Cookie 格式错误,无法存储。</strong></p>
<p>反正不是明确的告诉开发者长度异常了!!所以在使用 <code>cookieStore</code> 时,需要进行异常捕获。</p>
<p><strong>本文编写时 Firefox 最新版本 138.0.4 还不支持 cookieStore。</strong></p>
<h2 id="cookie-个数限制">Cookie 个数限制</h2>
<p>单个 Cookie 的大小限制了解了,再看看 Cookie 个数限制。</p>
<h3 id="多个超大-cookie">多个超大 Cookie</h3>
<p>测试代码:</p>
<pre><code class="language-js">(async () =&gt; {
document.cookie = ''
const name = 'name'
// 最大出入的 value 长度
let cookieStr = ''
for (let i = 0; i &lt; 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)
})()
</code></pre>
<p>第一次都能正常打开页面,第二次刷新页面之后都会报错:</p>
<p><img src="https://img2024.cnblogs.com/blog/596097/202507/596097-20250729105343348-421115177.png"></p>
<p>此问题应该是跟 http 协议的限制有关,请求头发送的 Cookie 长度太长了,导致响应 431 状态码。</p>
<p>Firefox 在页面未正常打卡的情况下还不支持清空 Cookie,需要点击<strong>右上角菜单--设置--隐私与安全--清除数据</strong>删除保存的超大 Cookie 浏览器才能正常访问。</p>
<h3 id="小-cookie-个数限制">小 Cookie 个数限制</h3>
<p>测试代码:</p>
<pre><code class="language-js">(async () =&gt; {
function setCookie(name, value) {
    return new Promise((resolve, reject) =&gt; {
      setTimeout(() =&gt; {
      document.cookie = `${name}=${value};path=/`;
      resolve()
      }, 5);
    });
}
const name = 'name'
// 最大出入的 value 长度
let cookieStr = ''
for (let i = 0; i &lt; 2000; i++) {
    console.log('正在写入:', i);
    await setCookie(name + i, 'a')
}
setTimeout(() =&gt; {
    // JS 查找 name 出现次数
    console.log(document.cookie?.match(/name/g)?.length)
}, 1000);
})()
</code></pre>
<p><strong>Chrome、Edge、Firefox 浏览器每次刷新写入的 Cookie 个数都不一样,可以复制以上代码在浏览器中测试!</strong></p>
<p>AI 回答:</p>
<p><img src="https://img2024.cnblogs.com/blog/596097/202507/596097-20250729105351318-703202126.png"></p>
<h2 id="写在最后">写在最后</h2>
<p>根据测试结果可以得出:在使用 Cookie 时只建议用于存入关键数据,而不是用来做相关缓存!!</p>


</div>
<div id="MySignature" role="contentinfo">
    <p>&nbsp;</p>
<p style="font-size: 18px;font-weight: bold;">文章首发于微信公众号【<span style="color:rgb(255, 71, 87)">前端路引</span>】,欢迎 <span style="color:#4ec259">微信扫一扫</span> 查看更多文章。</p>
<p>
<img style="max-width: 320px;" src="https://images.cnblogs.com/cnblogs_com/linx/2447020/o_250228035031_%E5%85%AC%E4%BC%97%E5%8F%B7%E4%BA%8C%E7%BB%B4%E7%A0%81.png"/>
</p>
<p>本文来自博客园,作者:前端路引,转载请注明原文链接:https://www.cnblogs.com/linx/p/19010392</p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/linx/p/19010392
頁: [1]
查看完整版本: Web前端入门第 82 问:JavaScript cookie 有大小限制吗?溢出会怎样?