Cho phép tiêu đề Access-Control-Allow-Origin bằng cách sử dụng API tìm nạp HTML5


87

Tôi đang sử dụng API tìm nạp HTML5.

var request = new Request('https://davidwalsh.name/demo/arsenal.json');

fetch(request).then(function(response) {
    // Convert to JSON
    return response.json();
}).then(function(j) {
    // Yay, `j` is a JavaScript object
    console.log(JSON.stringify(j));
}).catch(function(error) {
    console.log('Request failed', error)
});

Tôi có thể sử dụng json bình thường nhưng không thể tìm nạp dữ liệu của url api ở trên. Nó ném ra lỗi:

API tìm nạp không thể tải https://davidwalsh.name/demo/arsenal.json . Không có tiêu đề 'Access-Control-Allow-Origin' có trên tài nguyên được yêu cầu. Nguồn gốc ' http: // localhost ' do đó không được phép truy cập. Nếu phản hồi không rõ ràng phục vụ nhu cầu của bạn, hãy đặt chế độ của yêu cầu thành 'no-cors' để tìm nạp tài nguyên khi CORS bị vô hiệu hóa.


Máy chủ của bên thứ 3 cần thiết lập nó, bạn không thể làm gì ở phía máy khách.
epascarello

@epascarello: Chúng tôi có thể làm ở phía khách hàng. Phía sau hậu trường, Yêu cầu XHR đang diễn ra. Vui lòng kiểm tra điều nàyhttps://davidwalsh.name/fetch
iNikkz

Câu trả lời:


81

Giống như epascarello đã nói, máy chủ lưu trữ tài nguyên cần phải kích hoạt CORS. Những gì bạn có thể làm ở phía máy khách (và có thể là những gì bạn đang nghĩ đến) là đặt chế độ tìm nạp thành CORS (mặc dù tôi tin rằng đây là cài đặt mặc định):

fetch(request, {mode: 'cors'});

Tuy nhiên, điều này vẫn yêu cầu máy chủ bật CORS và cho phép miền của bạn yêu cầu tài nguyên.

Xem tài liệu CORSvideo Udacity tuyệt vời này giải thích Chính sách Nguồn gốc Giống nhau .

Bạn cũng có thể sử dụng chế độ no-cors ở phía máy khách, nhưng điều này sẽ chỉ cung cấp cho bạn một phản hồi không rõ ràng (bạn không thể đọc nội dung, nhưng phản hồi vẫn có thể được lưu trữ bởi nhân viên dịch vụ hoặc được sử dụng bởi một số API, chẳng hạn như <img>) :

fetch(request, {mode: 'no-cors'})
.then(function(response) {
  console.log(response); 
}).catch(function(error) {  
  console.log('Request failed', error)  
});

2
bạn có thể giải thích thêm về "Tuy nhiên, điều này vẫn yêu cầu máy chủ bật CORS và cho phép miền của bạn yêu cầu tài nguyên." Tôi đã không thành công khi tìm kiếm hướng dẫn để làm điều đó.
jayscript

2
@jayscript quy trình tổng thể trông giống như sau: trên máy khách, một yêu cầu nguồn gốc chéo được thực hiện với javascript. Trong trường hợp của API tìm nạp, chế độ 'cors' cho trình duyệt biết rằng có thể thực hiện yêu cầu này. Thay vào đó, nếu bạn có chế độ 'no-cors', trình duyệt sẽ dừng yêu cầu vì nó không phải nguồn gốc của ứng dụng của bạn. Máy chủ sẽ nhận yêu cầu và phản hồi. Các trình duyệt xác nhận rằng các phản ứng có các tiêu đề CORS thích hợp, và nếu như vậy, cho phép phản ứng để được đọc. Nếu tiêu đề không xuất hiện, trình duyệt sẽ báo lỗi.
David Scales

1
@jayscript bài viết MDN này đi vào chi tiết. Về cơ bản, một máy chủ của bạn mà bạn cần đặt các tiêu đề sau: "Access-Control-Allow-Origin: foo.example ", "Access-Control-Allow-Method: POST, GET, OPTIONS", "Access-Control-Allow-Headers: X-PINGOTHER, Content-Type ", cho phép các nguồn gốc, phương pháp và tiêu đề tương ứng. Điển hình là '*' được sử dụng cho nguồn gốc header.You cũng có thể kiểm tra tài liệu Google này và liên codelab để tìm hiểu về Fetch API: developers.google.com/web/ilt/pwa/working-with-the-fetch-api
David Scales

2
Cảm ơn bạn! Điều đó giúp tôi hiểu rằng không thể tìm nạp dữ liệu từ máy chủ API có nguồn gốc khác khi máy chủ API không chứa bất kỳ tiêu đề nào. Trong trường hợp cụ thể mà tôi đang giải quyết, tôi có quyền truy cập vào mã máy chủ API và có thể tự thêm tiêu đề, điều này cho phép tìm nạp.
jayscript

Thật ngu ngốc, vấn đề bảo mật với NO sendingcookie là gì và do đó cho phép CORS?
deathangel908

14

Tôi đã có mã giao diện người dùng của mình chạy trong http: // localhost: 3000 và API (mã phụ trợ) của tôi đang chạy tại http: // localhost: 5000

Đang sử dụng API tìm nạp để gọi API. Ban đầu, nó là lỗi "cors". Sau đó, thêm mã bên dưới này vào mã API phụ trợ của tôi, cho phép nguồn gốc và tiêu đề từ bất kỳ đâu.

let allowCrossDomain = function(req, res, next) {
  res.header('Access-Control-Allow-Origin', "*");
  res.header('Access-Control-Allow-Headers', "*");
  next();
}
app.use(allowCrossDomain);

Tuy nhiên, bạn nên hạn chế nguồn gốc của bạn trong trường hợp các môi trường khác như sân khấu, sản phẩm.


20
đây là một câu trả lời khủng khiếp. đây là một vấn đề bảo mật lớn. nếu bạn đang đọc cái này, VUI LÒNG KHÔNG LÀM ĐIỀU NÀY.
mjones.udri

1
Đây là lý do để thiết lập cục bộ. Ví dụ để làm một kinda pic nhanh. Có, có một rủi ro bảo mật nếu điều tương tự xảy ra đối với các môi trường có thể triển khai khác. Đối với địa phương tôi cảm thấy nó không "Tuy nhiên, bạn nên hạn chế việc bạn nguồn gốc trong trường hợp môi trường khác như sân khấu, sản".
smsivaprakaash

12

Điều này đã làm việc cho tôi:

npm install -g local-cors-proxy

Điểm cuối API mà chúng tôi muốn yêu cầu có vấn đề về CORS:

https://www.yourdomain.com/test/list

Khởi động Proxy:

lcp --proxyUrl https://www.yourdomain.com

 Proxy Active 

 Proxy Url: http://www.yourdomain.com:28080
 Proxy Partial: proxy
 PORT: 8010

Sau đó, trong mã khách hàng của bạn, điểm cuối API mới:

http://localhost:8010/proxy/test/list

Kết quả cuối cùng sẽ là một yêu cầu đến https://www.yourdomain.ie/test/list mà không có vấn đề CORS!


Vui lòng đảm bảo máy chủ đang chạy song song Giống như mở cửa sổ nhắc cmt mới và chạy mã lcp --proxyUrl yourdomain.com
Govarthanan Venunathan

8

Tôi biết đây là một bài đăng cũ hơn, nhưng tôi nhận thấy điều phù hợp để tôi khắc phục lỗi này là sử dụng địa chỉ IP của máy chủ của tôi thay vì sử dụng tên miền trong yêu cầu tìm nạp của tôi. Ví dụ:

#(original) var request = new Request('https://davidwalsh.name/demo/arsenal.json');
#use IP instead
var request = new Request('https://0.0.0.0/demo/arsenal.json');

fetch(request).then(function(response) {
    // Convert to JSON
    return response.json();
}).then(function(j) {
    // Yay, `j` is a JavaScript object
    console.log(JSON.stringify(j));
}).catch(function(error) {
    console.log('Request failed', error)
});

1

Nếu bạn đang sử dụng nginx, hãy thử cái này

#Control-Allow-Origin access

    # Authorization headers aren't passed in CORS preflight (OPTIONS) calls. Always return a 200 for options.
    add_header Access-Control-Allow-Credentials "true" always;
    add_header Access-Control-Allow-Origin "https://URL-WHERE-ORIGIN-FROM-HERE " always;
    add_header Access-Control-Allow-Methods "GET,OPTIONS" always;
    add_header Access-Control-Allow-Headers "x-csrf-token,authorization,content-type,accept,origin,x-requested-with,access-control-allow-origin" always;

    if ($request_method = OPTIONS ) {
        return 200;
    }


-3

Hãy xem https://expressjs.com/en/resources/middleware/cors.html Bạn phải sử dụng cors.

Tải về:

$ npm install cors
const cors = require('cors');
app.use(cors());

Bạn phải đặt mã này vào máy chủ nút của mình.


1
Làm thế nào bạn có thể biết nếu nó là máy chủ của OP và nó được viết bằng NodeJs?
Marek Szkudelski

Nếu bạn đã tạo một máy chủ nút (chế độ phát triển), bạn có thể sử dụng phương pháp đó để sử dụng tìm nạp trong js.
Ernersto Pastori
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.