Câu trả lời này bao gồm rất nhiều nền tảng, vì vậy nó được chia thành ba phần:
- Cách sử dụng proxy CORS để khắc phục các vấn đề về tiêu đề 'Không có quyền truy cập-Kiểm soát-Cho phép-Xuất xứ'
- Làm thế nào để tránh ánh sáng trước CORS
- Cách khắc phục tiêu đề của Access Access-Control-Allow-Origin không phải là vấn đề về ký tự đại diện
Cách sử dụng proxy CORS để khắc phục các vấn đề về tiêu đề 'Không có quyền truy cập-Kiểm soát-Cho phép-Xuất xứ'
Nếu bạn không kiểm soát máy chủ, mã JavaScript frontend của bạn đang gửi yêu cầu và vấn đề với phản hồi từ máy chủ đó chỉ là thiếu Access-Control-Allow-Origin
tiêu đề cần thiết , bạn vẫn có thể khiến mọi thứ hoạt động bằng cách thực hiện yêu cầu thông qua một Proxy CORS. Để hiển thị cách thức hoạt động, trước tiên, đây là một số mã không sử dụng proxy CORS:
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(url)
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))
Lý do catch
khối bị tấn công là, trình duyệt ngăn mã đó truy cập vào phản hồi từ đó https://example.com
. Và lý do trình duyệt làm điều đó là, phản hồi thiếu Access-Control-Allow-Origin
tiêu đề phản hồi.
Bây giờ, đây chính xác là ví dụ tương tự nhưng chỉ với một proxy CORS được thêm vào:
const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(proxyurl + url) // https://cors-anywhere.herokuapp.com/https://example.com
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))
Lưu ý: Nếu https://cors-anywhere.herokuapp.com không hoạt động hoặc không khả dụng khi bạn dùng thử, hãy xem bên dưới để biết cách triển khai máy chủ CORS Anywhere của bạn tại Heroku chỉ trong 2-3 phút.
Đoạn mã thứ hai ở trên có thể truy cập phản hồi thành công vì lấy URL yêu cầu và thay đổi nó thành https://cors-anywhere.herokuapp.com/https://example.com .byby chỉ cần thêm tiền tố vào URL proxy. yêu cầu được thực hiện thông qua proxy đó, sau đó:
- Chuyển tiếp yêu cầu đến
https://example.com
.
- Nhận được phản hồi từ
https://example.com
.
- Thêm
Access-Control-Allow-Origin
tiêu đề để trả lời.
- Chuyển phản hồi đó, với tiêu đề được thêm đó, trở lại mã giao diện yêu cầu.
Trình duyệt sau đó cho phép mã frontend truy cập vào phản hồi, bởi vì phản hồi đó với Access-Control-Allow-Origin
tiêu đề phản hồi là những gì trình duyệt nhìn thấy.
Bạn có thể dễ dàng chạy proxy của riêng mình bằng mã từ https://github.com/Rob--W/cors-anywhere/ .
Bạn cũng có thể dễ dàng triển khai proxy của riêng mình lên Heroku chỉ trong 2-3 phút, với 5 lệnh:
git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master
Sau khi chạy các lệnh đó, bạn sẽ kết thúc với máy chủ CORS Anywhere của mình đang chạy tại, ví dụ: https://cryptic-headland-94862.herokuapp.com/ . Vì vậy, thay vì tiền tố URL yêu cầu của bạn với https://cors-anywhere.herokuapp.com
, tiền tố thay vào đó bằng URL cho ví dụ của riêng bạn; ví dụ: https://cryptic-headland-94862.herokuapp.com/https://example.com .
Vì vậy, nếu khi bạn cố gắng sử dụng https://cors-anywhere.herokuapp.com, bạn sẽ thấy nó bị hỏng (đôi khi sẽ như vậy), sau đó xem xét lấy tài khoản Heroku (nếu bạn chưa có) và lấy 2 hoặc 3 phút để thực hiện các bước trên để triển khai máy chủ CORS Anywhere của riêng bạn trên Heroku.
Bất kể, cho dù bạn tự chạy hay sử dụng https://cors-anywhere.herokuapp.com hoặc proxy mở khác, giải pháp này vẫn hoạt động ngay cả khi yêu cầu là một trình duyệt kích hoạt yêu cầu trình duyệt trước CORS OPTIONS
vì trong trường hợp đó, proxy cũng gửi lại Access-Control-Allow-Headers
và Access-Control-Allow-Methods
các tiêu đề cần thiết để làm cho preflight thành công.
Làm thế nào để tránh ánh sáng trước CORS
Mã trong câu hỏi kích hoạt tiền tố CORS trước khi nó gửi một Authorization
tiêu đề.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_Vquests
Ngay cả khi không có điều đó, Content-Type: application/json
tiêu đề cũng sẽ kích hoạt preflight.
Điều gì có nghĩa là tiền tố của Nhật Bản: trước khi trình duyệt thử POST
mã trong câu hỏi, trước tiên, nó sẽ gửi OPTIONS
yêu cầu đến máy chủ - để xác định xem máy chủ có chọn tham gia nhận nguồn gốc chéo POST
bao gồm tiêu đề Authorization
và Content-Type: application/json
tiêu đề hay không.
Nó hoạt động khá tốt với một tập lệnh curl nhỏ - tôi lấy dữ liệu của mình.
Để kiểm tra đúng cách curl
, bạn phải mô phỏng OPTIONS
yêu cầu preflight mà trình duyệt gửi:
curl -i -X OPTIONS -H "Origin: http://127.0.0.1:3000" \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: Content-Type, Authorization' \
"https://the.sign_in.url"
... với https://the.sign_in.url
thay thế bởi bất cứ điều gì thực tế của bạn sign_in
URL.
Phản hồi mà trình duyệt cần xem từ OPTIONS
yêu cầu đó phải bao gồm các tiêu đề như thế này:
Access-Control-Allow-Origin: http://127.0.0.1:3000
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization
Nếu OPTIONS
phản hồi không bao gồm các tiêu đề đó, thì trình duyệt sẽ dừng ngay tại đó và thậm chí không bao giờ cố gắng gửi POST
yêu cầu. Ngoài ra, mã trạng thái HTTP cho phản hồi phải là 2xx, thường là 200 hoặc 204. Nếu đó là bất kỳ mã trạng thái nào khác, trình duyệt sẽ dừng ngay tại đó.
Máy chủ trong câu hỏi đang trả lời OPTIONS
yêu cầu bằng mã trạng thái 501, điều này rõ ràng có nghĩa là nó đang cố gắng chỉ ra rằng nó không thực hiện hỗ trợ cho OPTIONS
các yêu cầu. Các máy chủ khác thường phản hồi với Phương thức 405 không được phép sử dụng mã trạng thái trong trường hợp này.
Vì vậy, bạn sẽ không bao giờ có thể thực hiện POST
các yêu cầu trực tiếp đến máy chủ đó từ mã JavaScript frontend của mình nếu máy chủ đáp ứng OPTIONS
yêu cầu đó bằng 405 hoặc 501 hoặc bất cứ điều gì khác ngoài 200 hoặc 204 hoặc nếu không đáp ứng với những điều cần thiết đó tiêu đề phản hồi.
Cách để tránh kích hoạt một ánh sáng trước cho trường hợp trong câu hỏi sẽ là:
- nếu máy chủ không yêu
Authorization
cầu tiêu đề yêu cầu mà thay vào đó (ví dụ) dựa vào dữ liệu xác thực được nhúng trong phần thân của POST
yêu cầu hoặc dưới dạng tham số truy vấn
- nếu máy chủ không yêu cầu phần
POST
thân phải có Content-Type: application/json
loại phương tiện mà thay vào đó chấp nhận phần POST
thân như application/x-www-form-urlencoded
với một tham số có tên json
(hoặc bất cứ thứ gì) có giá trị là dữ liệu JSON
Cách khắc phục tiêu đề của Access Access-Control-Allow-Origin không phải là vấn đề về ký tự đại diện
Tôi nhận được một thông báo lỗi khác:
Giá trị của tiêu đề 'Kiểm soát truy cập-Cho phép-Xuất xứ' trong phản hồi không được là ký tự đại diện '*' khi chế độ thông tin đăng nhập của yêu cầu là 'bao gồm'. Do đó, nguồn gốc ' http://127.0.0.1:3000 ' không được phép truy cập. Chế độ thông tin xác thực của các yêu cầu do XMLHttpRequest khởi xướng được kiểm soát bởi thuộc tính withCredentials.
Đối với yêu cầu bao gồm thông tin đăng nhập, các trình duyệt sẽ không cho phép mã JavaScript frontend của bạn truy cập vào phản hồi nếu giá trị của Access-Control-Allow-Origin
tiêu đề phản hồi là *
. Thay vào đó, giá trị trong trường hợp đó phải khớp chính xác với nguồn gốc của mã frontend của bạn , http://127.0.0.1:3000
.
Xem các yêu cầu được xác thực và ký tự đại diện trong bài viết Kiểm soát truy cập HTTP (CORS) MDN.
Nếu bạn kiểm soát máy chủ mà bạn đang gửi yêu cầu, thì một cách phổ biến để giải quyết trường hợp này là cấu hình máy chủ để lấy giá trị của Origin
tiêu đề yêu cầu và phản hồi / phản ánh lại giá trị của Access-Control-Allow-Origin
tiêu đề phản hồi. Ví dụ: với nginx:
add_header Access-Control-Allow-Origin $http_origin
Nhưng đó chỉ là một ví dụ; hệ thống máy chủ (web) khác cung cấp các cách tương tự với giá trị gốc echo.
Tôi đang sử dụng Chrome. Tôi cũng đã thử sử dụng Plugin Chrome CORS đó
Plugin Chrome CORS rõ ràng chỉ đơn giản là tiêm một Access-Control-Allow-Origin: *
tiêu đề vào phản hồi mà trình duyệt nhìn thấy. Nếu plugin thông minh hơn, những gì nó sẽ làm là đặt giá trị của Access-Control-Allow-Origin
tiêu đề phản hồi giả mạo đó thành nguồn gốc thực tế của mã JavaScript frontend của bạn , http://127.0.0.1:3000
.
Vì vậy, tránh sử dụng plugin đó, ngay cả để thử nghiệm. Nó chỉ là một sự xao lãng. Nếu bạn muốn kiểm tra những phản hồi bạn nhận được từ máy chủ mà không có trình duyệt lọc chúng, bạn nên sử dụng curl -H
như trên.
Theo như mã JavaScript frontend cho fetch(…)
yêu cầu trong câu hỏi:
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
Loại bỏ những dòng. Các Access-Control-Allow-*
tiêu đề là tiêu đề phản ứng . Bạn không bao giờ muốn gửi chúng trong một yêu cầu. Hiệu ứng duy nhất sẽ có là kích hoạt trình duyệt để thực hiện một ánh sáng trước.