Công thức bánh quy SameSite

Chrome, Firefox, Edge và các nền tảng khác sẽ thay đổi hành vi mặc định phù hợp với đề xuất của IETF, Cookie tốt hơn tăng dần để:

  • Cookie không có thuộc tính SameSite sẽ được coi là SameSite=Lax, nghĩa là hành vi mặc định sẽ là chỉ việc hạn chế cookie đối với ngữ cảnh của bên thứ nhất.
  • Cookie để sử dụng trên nhiều trang web phải chỉ định SameSite=None; Secure để cho phép đưa vào ngữ cảnh bên thứ ba.

Tính năng này là hành vi mặc định từ phiên bản ổn định của Chrome 84 trở đi. Nếu chưa thực hiện việc này, bạn nên cập nhật các thuộc tính cho cookie của bên thứ ba để cookie của bên thứ ba không bị chặn trong tương lai.

Hỗ trợ trên nhiều trình duyệt

Hãy xem phần Khả năng tương thích với trình duyệt trên trang Set-Cookie của MDN.

Các trường hợp sử dụng cookie trên nhiều trang web hoặc cookie của bên thứ ba

Có một số trường hợp sử dụng và mẫu phổ biến mà cần được gửi cookie trong ngữ cảnh bên thứ ba. Nếu bạn cung cấp hoặc phụ thuộc vào một trong các trường hợp sử dụng này, hãy đảm bảo rằng bạn hoặc nhà cung cấp đang cập nhật cookie để đảm bảo dịch vụ tiếp tục hoạt động chính xác.

Nội dung trong <iframe>

Nội dung trên một trang web khác hiển thị trong <iframe> là nội dung của bên thứ ba. Sau đây là các trường hợp sử dụng tiêu chuẩn:

  • Nội dung được nhúng được chia sẻ từ các trang web khác, chẳng hạn như video, bản đồ, mã mẫu và bài đăng trên mạng xã hội.
  • Tiện ích của các dịch vụ bên ngoài, chẳng hạn như chức năng thanh toán, lịch, đặt trước và đặt trước.
  • Các tiện ích như nút mạng xã hội hoặc dịch vụ chống gian lận tạo ra <iframes> kém rõ ràng hơn.

Có thể sử dụng cookie ở đây để cùng nhiều hoạt động khác duy trì trạng thái phiên, lưu trữ các lựa chọn ưu tiên chung, bật số liệu thống kê hoặc cá nhân hoá nội dung cho những người dùng có tài khoản hiện có.

Sơ đồ cửa sổ trình duyệt nơi URL của nội dung được nhúng không khớp với URL của trang.
Nếu nội dung được nhúng không đến từ cùng một trang web với bối cảnh duyệt web cấp cao nhất, thì đó là nội dung của bên thứ ba.

Ngoài ra, do web vốn có khả năng kết hợp, nên <iframes> được dùng để nhúng nội dung cũng được xem trong bối cảnh cấp cao nhất hoặc bên thứ nhất. Mọi cookie mà trang web đó sử dụng đều sẽ được coi là cookie của bên thứ ba khi trang web hiển thị trong khung. Nếu đang tạo các trang web mà bạn dự định dễ dàng được người khác nhúng vào trong khi vẫn dựa vào cookie để hoạt động, bạn cũng cần đảm bảo các trang web đó được đánh dấu để sử dụng trên nhiều trang web hoặc bạn có thể dự phòng dễ dàng mà không cần cookie.

Yêu cầu "Không an toàn" trên các trang web

Mặc dù "không an toàn" nghe có vẻ hơi đáng lo ngại ở đây, nhưng dùng để chỉ mọi yêu cầu có thể nhằm thay đổi trạng thái. Trên web chủ yếu là các yêu cầu POST. Những cookie được đánh dấu là SameSite=Lax sẽ được gửi thông qua các thành phần điều hướng cấp cao nhất an toàn, ví dụ: nhấp vào một đường liên kết để chuyển đến một trang web khác. Tuy nhiên, một trường hợp như <form> gửi qua POST đến một trang web khác sẽ không bao gồm cookie.

Sơ đồ về một yêu cầu di chuyển từ trang này sang trang khác.
Nếu yêu cầu đến sử dụng phương thức "an toàn", thì cookie sẽ được gửi.

Mẫu này được dùng cho các trang web có thể chuyển hướng người dùng đến một dịch vụ từ xa để thực hiện một số thao tác trước khi quay lại, chẳng hạn như chuyển hướng đến một nhà cung cấp danh tính bên thứ ba. Trước khi người dùng rời khỏi trang web, một cookie được đặt chứa một mã thông báo sử dụng với kỳ vọng rằng mã thông báo này có thể được kiểm tra trong yêu cầu trả về để giảm thiểu các cuộc tấn công Giả mạo yêu cầu trên nhiều trang web (CSRF). Nếu yêu cầu trả về đó đến qua yêu cầu POST, thì bạn cần đánh dấu các cookie đó là SameSite=None; Secure.

Tài nguyên từ xa

Mọi tài nguyên từ xa trên một trang đều có thể dựa vào cookie được gửi cùng với yêu cầu, từ các thẻ <img>, thẻ <script>, v.v. Các trường hợp sử dụng phổ biến bao gồm pixel theo dõi và cá nhân hoá nội dung.

Điều này cũng áp dụng cho các yêu cầu do fetch hoặc XMLHttpRequest bắt đầu từ JavaScript của bạn. Nếu fetch() được gọi bằng tuỳ chọn credentials: 'include', đây là một dấu hiệu tốt cho thấy cookie có thể được dự kiến trong các yêu cầu đó. Đối với XMLHttpRequest, bạn nên tìm các thực thể của thuộc tính withCredentials đang được đặt thành true. Đây là một chỉ báo tốt cho thấy cookie có thể được dự kiến trong các yêu cầu đó. Bạn cần đánh dấu các cookie đó một cách phù hợp để đưa vào các yêu cầu trên nhiều trang web.

Nội dung trong WebView

WebView trong ứng dụng dành riêng cho nền tảng được một trình duyệt hỗ trợ và bạn sẽ cần kiểm thử xem có các quy định hạn chế hoặc vấn đề tương tự hay không. Trong Android, nếu WebView được Chrome hỗ trợ, thì các chế độ mặc định mới sẽ không được áp dụng ngay với Chrome 84. Tuy nhiên, mục đích là áp dụng trong tương lai, vì vậy, bạn vẫn nên kiểm thử và chuẩn bị cho việc này. Ngoài ra, Android cho phép các ứng dụng dành riêng cho nền tảng đặt cookie trực tiếp thông qua CookieManager API. Tương tự như với các cookie được đặt qua tiêu đề hoặc JavaScript, hãy cân nhắc thêm SameSite=None; Secure nếu bạn dùng cookie này trên nhiều trang web.

Cách triển khai SameSite ngay hôm nay

Đối với những cookie chỉ cần thiết trong ngữ cảnh bên thứ nhất, tốt nhất bạn nên đánh dấu các cookie này là SameSite=Lax hoặc SameSite=Strict tuỳ thuộc vào nhu cầu của mình. Bạn cũng có thể chọn không làm gì và chỉ cho phép trình duyệt thực thi chế độ mặc định. Tuy nhiên, điều này có nguy cơ dẫn đến hành vi không nhất quán trên các trình duyệt và có thể có cảnh báo trên bảng điều khiển cho từng cookie.

Set-Cookie: first_party_var=value; SameSite=Lax

Đối với những cookie cần thiết trong ngữ cảnh của bên thứ ba, bạn cần đảm bảo các cookie này được đánh dấu là SameSite=None; Secure. Xin lưu ý rằng bạn cần phải có cả hai thuộc tính. Nếu bạn chỉ chỉ định None mà không có Secure, thì cookie sẽ bị từ chối. Tuy nhiên, có một số điểm khác biệt không tương thích lẫn nhau trong các cách triển khai trình duyệt. Vì vậy, bạn có thể cần sử dụng một số chiến lược giảm thiểu được mô tả trong phần Xử lý các ứng dụng không tương thích dưới đây.

Set-Cookie: third_party_var=value; SameSite=None; Secure

Xử lý các ứng dụng không tương thích

Vì những thay đổi này để bao gồm None và cập nhật hành vi mặc định vẫn còn tương đối mới, nên có sự không thống nhất giữa các trình duyệt về cách xử lý những thay đổi này. Bạn có thể tham khảo trang thông tin cập nhật trên chromium.org để biết các vấn đề hiện đã biết. Tuy nhiên, chúng tôi không thể cho biết liệu đây là toàn bộ các vấn đề. Mặc dù điều này không lý tưởng, nhưng bạn có thể sử dụng một số giải pháp khác trong giai đoạn chuyển đổi này. Tuy nhiên, nguyên tắc chung là xem các ứng dụng không tương thích là trường hợp đặc biệt. Không tạo trường hợp ngoại lệ cho các trình duyệt triển khai quy tắc mới.

Tuỳ chọn đầu tiên là đặt cả cookie kiểu mới và cookie kiểu cũ:

Set-cookie: 3pcookie=value; SameSite=None; Secure
Set-cookie: 3pcookie-legacy=value; Secure

Các trình duyệt triển khai hành vi mới hơn sẽ đặt cookie có giá trị SameSite, trong khi các trình duyệt khác có thể bỏ qua hoặc đặt giá trị này không chính xác. Tuy nhiên, chính các trình duyệt đó sẽ đặt cookie 3pcookie-legacy. Khi xử lý cookie đi kèm, trước tiên trang web phải kiểm tra sự hiện diện của cookie kiểu mới và nếu không tìm thấy cookie kiểu mới, thì hãy dự phòng cookie cũ.

Ví dụ bên dưới cho thấy cách thực hiện việc này trong Node.js, bằng cách sử dụng khung Express và phần mềm trung gian cookie-parser.

const express = require('express');
const cp = require('cookie-parser');
const app = express();
app.use(cp());

app.get('/set', (req, res) => {
  // Set the new style cookie
  res.cookie('3pcookie', 'value', { sameSite: 'none', secure: true });
  // And set the same value in the legacy cookie
  res.cookie('3pcookie-legacy', 'value', { secure: true });
  res.end();
});

app.get('/', (req, res) => {
  let cookieVal = null;

  if (req.cookies['3pcookie']) {
    // check the new style cookie first
    cookieVal = req.cookies['3pcookie'];
  } else if (req.cookies['3pcookie-legacy']) {
    // otherwise fall back to the legacy cookie
    cookieVal = req.cookies['3pcookie-legacy'];
  }

  res.end();
});

app.listen(process.env.PORT);

Nhược điểm là việc này liên quan đến việc đặt cookie dự phòng để bao gồm tất cả trình duyệt và đòi hỏi phải thực hiện các thay đổi cả tại thời điểm cài đặt và đọc cookie. Tuy nhiên, phương pháp này phải áp dụng cho tất cả trình duyệt bất kể hành vi của chúng là gì và đảm bảo cookie của bên thứ ba tiếp tục hoạt động như trước đây.

Ngoài ra, tại thời điểm gửi tiêu đề Set-Cookie, bạn có thể chọn phát hiện ứng dụng thông qua chuỗi tác nhân người dùng. Tham khảo danh sách các ứng dụng không tương thích, sau đó sử dụng thư viện thích hợp cho nền tảng của bạn, ví dụ: thư viện ua-parser-js trên Node.js. Bạn nên tìm một thư viện để xử lý việc phát hiện tác nhân người dùng vì có lẽ bạn không muốn tự viết các biểu thức chính quy đó.

Lợi ích của phương pháp này là chỉ yêu cầu thực hiện một thay đổi tại thời điểm đặt cookie. Tuy nhiên, cảnh báo cần thiết ở đây là việc phát hiện tác nhân người dùng vốn rất dễ bị tổn thương và có thể không phát hiện được tất cả người dùng bị ảnh hưởng.

Hỗ trợ SameSite=None bằng các ngôn ngữ, thư viện và khung

Phần lớn ngôn ngữ và thư viện đều hỗ trợ thuộc tính SameSite cho cookie. Tuy nhiên, việc thêm SameSite=None vẫn còn tương đối mới, có nghĩa là hiện tại bạn có thể phải giải quyết một số hành vi chuẩn. Những ví dụ này được ghi lại trong kho lưu trữ ví dụ về SameSite trên GitHub.

Nhận trợ giúp

Cookie có ở khắp mọi nơi và hiếm khi có trang web nào kiểm tra đầy đủ vị trí đặt và sử dụng cookie, đặc biệt là khi bạn loại bỏ các trường hợp sử dụng trên nhiều trang web. Khi bạn gặp một vấn đề, đây có thể là lần đầu tiên bất kỳ ai gặp phải vấn đề đó - vì vậy, đừng ngần ngại liên hệ với chúng tôi: