Chia sẻ tài nguyên nhiều nguồn gốc một cách an toàn
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?
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 đề và phần thân.
Đầu trang
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ặcContent-Language
. - Yêu cầu có tiêu đề
Content-Type
khác vớiapplication/x-www-form-urlencoded
,multipart/form-data
hoặctext/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.