Web前端入門第 81 問:JavaScript cookie 的讀寫操作
前端的 cookie 讀寫在 2020 年之前一直不存在一個官方的接口,每次需要使用 cookie 的時候,要么是引入三方插件,要么就需要自己封裝一個公用的組件或函數。
npm 的 cookie 插件周下載量 6 千萬左右,可以想象一下此功能在前端的應用場景有多么廣泛~~
cookie 插件: https://www.npmjs.com/package/cookie
cookie 用途
cookie 一般多用于存儲標識符,比如用戶身份標識(登錄狀態),個性化設置的一些標識(語言設置,主題設置等等),用戶行為跟蹤標識(跟蹤用戶點擊行為等)。
以前還有很多的廣告商用于跟蹤用戶行為,現在由于瀏覽器的安全機制越來越嚴格,廣告商基本不再使用 cookie 跟蹤用戶信息,轉而使用瀏覽器的指紋特征來做跟蹤記錄。瀏覽器指紋可參考文章:瀏覽器 15 個常見指紋特征,使用插件 FingerprintJS 生成瀏覽器指紋
cookie 安全問題
由于 cookie 存儲在用戶瀏覽器,極易被嵌入的三方代碼獲取,用于 XSS 攻擊,CSRF 跨站請求偽造等等。
所以在使用 cookie 存儲關鍵信息時候,需要注意配置 cookie 的安全屬性,比如:過期時間(expires)、安全(secure)、sameSite等。
cookie 相關屬性
name:記錄 cookie 名稱的字符串。
value:記錄 cookie 值。
domain:表示 cookie 的所屬域,跨域不能訪問。
expires:表示 cookie 的過期時間,使用 unix 時間戳,不設置默認是會話結束,即瀏覽器關閉就失效。
path:記錄 cookie 路徑的字符串,設置了路徑之后,跨路徑無法訪問。默認為 /。
partitioned:cookie是否分區,實驗性質。
sameSite:設置跨站點請求中是否發送cookie。
secure:設置后表示只能通過 HTTPS 協議訪問。
以下屬性僅支持后端設置,前端無法處理。
httpOnly:設置后客戶端腳本(即瀏覽器端)無法訪問 cookie。
cookie 存儲方法
最原始的 cookie 存儲方法只能使用 document.cookie 屬性,讀寫操作都只能通過它~~
例如一個完整的設置 cookie 的代碼:
document.cookie = `name=${encodeURIComponent('前端路引')};expires=${new Date(2026, 0, 1).toGMTString()};path=/;Secure;SameSite=Lax`;
注意:寫入 cookie 的屬性值不能存在換行,換行無效,代碼也不會報錯,比如:
// 由于有換行符存在以下代碼瀏覽器不報錯,也不會寫入cookie
document.cookie = `
name=${encodeURIComponent('前端路引')};
expires=${new Date(2026, 0, 1).toGMTString()};
path=/;
domain=localhost;
Secure;
SameSite=Lax
`;
取值:
const name = document.cookie.split(';').find(item => item.trim().startsWith('name=')).split('=')[1]
console.log(decodeURIComponent(name))
這種讀寫方法始終不太方便,然后可以稍稍的封裝一下:
/**
* 獲取或者設置cookie
* @param name {String} cookie名
* @param value {String} cookie值,如果傳遞該參數,則直接取值
* @param days {Number} 設置cookie有效天數
* @return 如果取值,則返回值,沒值則返回null
*/
function cookie (name, value, days) {
if (value !== undefined) {
if (days === undefined || days === null || days === '') {
document.cookie = name + '=' + encodeURIComponent(value) + '; path=/;';
return;
}
days = isNaN(days) ? 0 : days;
var exp = new Date();
exp.setTime(exp.getTime() + days * 24 * 60 * 60 * 1000);
document.cookie = name + '=' + encodeURIComponent(value) + '; path=/;expires=' + exp.toGMTString();
} else {
var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)');
var arr = document.cookie.match(reg);
if (arr) {
return decodeURIComponent(arr[2]);
} else {
return null;
}
}
}
以上代碼只是一個基礎的封裝使用,可以基于此擴展一下其他配置項!!也可以直接下載 npm 開源的 cookie/js-cookie 插件。
CookieStore
document.cookie 操作 cookie 需要對字符串進行處理,如果存在多個 cookie 的情況下,處理起來就更麻煩,所以在 2020 年 JS 標準就新增了 CookieStore 接口,用于管理 cookie。此接口大大的簡化了 cookie 的讀寫操作,用起來也更加方便。
CookieStore 只能在 https 或者 localhost 下使用,所以不再支持 Secure 配置,默認就是在 https 中傳輸。
CookieStore 對象就四個方法,都返回 Promise 對象:
// 刪除
cookieStore.delete() // 返回 Promise
// 獲取
cookieStore.get() // 返回 Promise
// 獲取全部
cookieStore.getAll() // 返回 Promise
// 寫入
cookieStore.set() // 返回 Promise
// 支持change事件用于監聽 Cookie 變化
cookieStore.addEventListener("change", (event) => { })
cookieStore.onchange = (event) => { }
使用示例:
(async () => {
cookieStore.addEventListener("change", (event) => {
console.log(event.changed);
})
cookieStore.onchange = (event) => {
console.log(event.changed);
}
await cookieStore.set('name', '公眾號')
await cookieStore.get('name').then(value => {
console.log(value)
})
await cookieStore.delete('name').then(() => {
console.log('刪除成功')
})
await cookieStore.set({
name: 'name',
value: '前端路引',
expires: new Date(2026, 0, 1).getTime(), // Unix 時間戳(以毫秒為單位表示)
path: '/',
secure: true, // 不支持設置
sameSite: 'lax'
})
await cookieStore.get({
name: 'name',
url: window.location.href
}).then(value => {
console.log(value)
})
await cookieStore.set('type', '公眾號')
await cookieStore.getAll().then(values => {
console.log(values)
})
})()
更多用法參考 MDN 文檔:https://developer.mozilla.org/zh-CN/docs/Web/API/CookieStore
寫在最后
cookieStore 可以大大簡化前端讀寫 cookie 的復雜度,但由于其 API 引入時間較晚,基本都是在 2020 年之后的瀏覽器才開始支持,所以在使用時請注意瀏覽器兼容情況。
在使用 Cookie 保存敏感數據時,請務必注意數據安全,比如存儲用戶的身份令牌,如果身份令牌被三方代碼獲取,及其容易造成跨站請求偽造,導致用戶信息泄露!!

浙公網安備 33010602011771號