Chia sẻ tài nguyên trên nhiều nguồn gốc (CORS)

Chia sẻ tài nguyên nhiều nguồn gốc một cách an toàn

Mariko Kosaka

Chính sách cùng nguồn gốc của trình duyệt sẽ chặn việc đọc tài nguyên từ một nguồn gốc khác. Cơ chế này ngăn các trang web độc hại đọc dữ liệu của các trang web khác, nhưng cũng ngăn chặn các trường hợp sử dụng hợp pháp.

Các ứng dụng web hiện đại thường muốn lấy tài nguyên từ một nguồn gốc khác, chẳng hạn như truy xuất dữ liệu JSON qua một miền khác hoặc tải hình ảnh từ một trang web khác vào phần tử <canvas>. Đây có thể là các tài nguyên công khai mà ai cũng có thể đọc, nhưng chính sách cùng nguồn gốc sẽ chặn việc sử dụng các tài nguyên đó. Trước đây, các nhà phát triển thường sử dụng một số giải pháp như JSONP.

Tính năng Chia sẻ tài nguyên trên nhiều nguồn gốc (CORS) sẽ khắc phục vấn đề này theo cách chuẩn hoá. Khi bạn bật CORS, máy chủ có thể thông báo cho trình duyệt biết rằng nó có thể sử dụng một nguồn gốc khác.

Yêu cầu tài nguyên hoạt động như thế nào trên web?

yêu cầu và phản hồi
Hình minh hoạ yêu cầu của ứng dụng và phản hồi của máy chủ.

Trình duyệt và máy chủ có thể trao đổi dữ liệu qua mạng bằng Giao thức truyền siêu văn bản (HTTP). HTTP xác định các quy tắc giao tiếp giữa người yêu cầu và người phản hồi, bao gồm cả những thông tin cần thiết để nhận tài nguyên.

Tiêu đề HTTP thương lượng việc trao đổi thông báo giữa ứng dụng và máy chủ, đồng thời được dùng để xác định quyền truy cập. Cả yêu cầu của trình duyệt và thông báo phản hồi của máy chủ đều được chia thành tiêu đềphần thân.

Thông tin về thông báo, chẳng hạn như loại thông báo hoặc phương thức mã hoá thông báo. Tiêu đề có thể chứa nhiều thông tin được biểu thị dưới dạng cặp khoá-giá trị. Tiêu đề yêu cầu và tiêu đề phản hồi chứa thông tin khác nhau.

Tiêu đề yêu cầu mẫu

Accept: text/html
Cookie: Version=1

Tiêu đề này tương đương với việc nói "Tôi muốn nhận HTML để phản hồi. Đây là bánh quy tôi có."

Tiêu đề phản hồi mẫu

Content-Encoding: gzip
Cache-Control: no-store

Tiêu đề này tương đương với việc nói "Dữ liệu trong phản hồi này được mã hoá bằng gzip. Đừng lưu dữ liệu này vào bộ nhớ đệm."

Nội dung

Chính thông báo đó. Đó có thể là văn bản thuần tuý, tệp nhị phân của hình ảnh, JSON, HTML hoặc nhiều định dạng khác.

CORS hoạt động như thế nào?

Chính sách cùng nguồn gốc sẽ cho trình duyệt biết để chặn các yêu cầu trên nhiều nguồn gốc. Khi bạn cần một tài nguyên công khai từ một nguồn gốc khác, máy chủ cung cấp tài nguyên sẽ cho trình duyệt biết rằng nguồn gốc gửi yêu cầu có thể truy cập vào tài nguyên của nó. Trình duyệt ghi nhớ điều đó và cho phép chia sẻ tài nguyên nhiều nguồn gốc cho tài nguyên đó.

Bước 1: yêu cầu ứng dụng (trình duyệt)

Khi trình duyệt gửi một yêu cầu nhiều nguồn gốc, trình duyệt sẽ thêm một tiêu đề Origin có nguồn gốc hiện tại (lược đồ, máy chủ và cổng).

Bước 2: phản hồi của máy chủ

Khi nhìn thấy tiêu đề này và muốn cho phép truy cập, máy chủ sẽ thêm tiêu đề Access-Control-Allow-Origin vào phản hồi chỉ định nguồn gốc yêu cầu (hoặc * để cho phép nguồn gốc bất kỳ).

Bước 3: trình duyệt nhận phản hồi

Khi thấy phản hồi này có tiêu đề Access-Control-Allow-Origin thích hợp, trình duyệt sẽ chia sẻ dữ liệu phản hồi với trang web ứng dụng.

Chia sẻ thông tin đăng nhập với CORS

Vì lý do liên quan đến quyền riêng tư, CORS thường dùng cho các yêu cầu ẩn danh mà trong đó người yêu cầu không được xác định. Nếu muốn gửi cookie khi sử dụng CORS (có thể xác định người gửi), thì bạn cần thêm tiêu đề bổ sung vào yêu cầu và phản hồi.

Yêu cầu

Thêm credentials: 'include' vào các tuỳ chọn tìm nạp như trong ví dụ sau. Điều này bao gồm cookie với yêu cầu như sau:

fetch('https://example.com', {
  mode: 'cors',
  credentials: 'include'
})

Phản hồi

Bạn phải đặt Access-Control-Allow-Origin thành một nguồn gốc cụ thể (không sử dụng ký tự đại diện *) và phải đặt Access-Control-Allow-Credentials thành true.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

Các yêu cầu kiểm tra trước đối với lệnh gọi HTTP phức tạp

Khi một ứng dụng web đưa ra một yêu cầu HTTP phức tạp, trình duyệt sẽ thêm một yêu cầu kiểm tra vào đầu chuỗi yêu cầu.

Thông số kỹ thuật của CORS xác định một yêu cầu phức tạp như sau:

  • Yêu cầu sử dụng các phương thức không phải là GET, POST hoặc head.
  • Yêu cầu bao gồm các tiêu đề không phải là Accept, Accept-Language hoặc Content-Language.
  • Yêu cầu có tiêu đề Content-Type khác với application/x-www-form-urlencoded, multipart/form-data hoặc text/plain.

Các trình duyệt sẽ tự động tạo mọi yêu cầu kiểm tra trước cần thiết và gửi các yêu cầu đó trước thông báo yêu cầu thực tế. Yêu cầu kiểm tra là một yêu cầu OPTIONS như ví dụ sau:

OPTIONS /data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: DELETE

Về phía máy chủ, ứng dụng nhận được yêu cầu này sẽ phản hồi yêu cầu kiểm tra trước bằng thông tin về các phương thức mà ứng dụng chấp nhận từ nguồn gốc sau:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, DELETE, HEAD, OPTIONS

Phản hồi của máy chủ cũng có thể bao gồm tiêu đề Access-Control-Max-Age để chỉ định thời lượng tính bằng giây để lưu kết quả kiểm tra vào bộ nhớ đệm. Điều này cho phép ứng dụng gửi nhiều yêu cầu phức tạp mà không cần lặp lại yêu cầu kiểm tra trước.