Дозволити заголовок Access-Control-Allow-Origin за допомогою API завантаження HTML5


87

Я використовую API вибору 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)
});

Я можу використовувати звичайний json, але не можу отримати дані вище URL-адреси api. Це видає помилку:

API Fetch не може завантажити https://davidwalsh.name/demo/arsenal.json . На запитаному ресурсі немає заголовка 'Access-Control-Allow-Origin'. Отже, походження ' http: // localhost ' не має доступу. Якщо непрозора відповідь відповідає вашим потребам, встановіть режим запиту на "no-cors", щоб отримати ресурс із вимкненою системою CORS.


Сторонній сервер повинен це встановити, ви нічого не можете зробити на стороні клієнта.
epascarello

@epascarello: Ми можемо робити на стороні клієнта. За лаштунками триває запит XHR. Будь ласка, перевірте цеhttps://davidwalsh.name/fetch
iNikkz

Відповіді:


81

Як сказав epascarello, сервер, на якому розміщений ресурс, повинен мати ввімкнену CORS. Те, що ви можете зробити на стороні клієнта (і, мабуть, те, про що ви думаєте), - це встановити режим вибору на CORS (хоча це налаштування за замовчуванням, я вважаю):

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

Однак для цього все ще потрібно, щоб сервер також увімкнув CORS і дозволив вашому домену запитувати ресурс.

Ознайомтеся з документацією CORS та цим чудовим відео Udacity, що пояснює ту саму політику походження .

Ви також можете використовувати режим no-cors на стороні клієнта, але це просто дасть вам непрозору відповідь (ви не можете прочитати тіло, але відповідь все одно може бути кешована службовцем або споживатися деякими API, наприклад <img>) :

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

2
Ви можете детальніше сказати "Однак для цього все-таки потрібно, щоб сервер також увімкнув CORS і дозволив домену запитувати ресурс."? Я безуспішно шукав інструкцій для цього.
jayscript

2
@jayscript загальний процес виглядає так: у клієнта запит на перехресне походження робиться за допомогою javascript. У випадку з API вибору, режим "cors" повідомляє браузеру, що це нормально робити цей запит. Якби замість цього у вас був режим "без корків", браузер зупинив би запит, оскільки він не відповідає джерелу вашого додатка. Сервер отримає запит і відповість. У браузері підтверджує , що відповідь має відповідні CORS заголовки, і якщо так, то дозволяє відповідь для читання. Якщо заголовків немає, браузер видасть помилку.
Девід

1
@jayscript ця стаття MDN йде в подробиці. По суті, одному вашому серверу потрібно встановити ці заголовки: "Access-Control-Allow-Origin: foo.example ", "Access-Control-Allow-Methods: POST, GET, OPTIONS", "Access-Control-Allow-Headers: X-PINGOTHER, Content-Type ", які дозволяють джерела, методи та заголовки відповідно. Зазвичай для заголовка джерела використовується "*". Ви також можете перевірити цей документ Google та пов'язану з ним лабораторну лабораторію, щоб дізнатися про Fetch API: developers.google.com/web/ilt/pwa/working-with-the-fetch-api
David Scales

2
Дякую! Це допомагає мені зрозуміти, що неможливо отримати дані з сервера API, який має інше походження, коли сервер API не містить заголовків. У тому конкретному випадку, з яким я мав справу, я мав доступ до коду сервера API і міг самостійно додавати заголовки, що дозволило отримати.
jayscript

Це німо, яка проблема безпеки з NO sendingфайлами cookie і, таким чином, дозволом CORS?
deathangel908

14

У мене був інтерфейсний код, який працював у http: // localhost: 3000, а мій API (кодовий код) працював на http: // localhost: 5000

Використовував API вибору для виклику API. Спочатку це була мета "помилки". Потім додав цей наведений нижче код до мого коду Backend API, дозволяючи початок та заголовок з будь-якого місця.

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

Однак слід обмежити своє походження у випадку інших середовищ, таких як stage, prod.


20
це жахлива відповідь. це величезна проблема безпеки. якщо ви читаєте це, будь ласка, НЕ робіть цього.
mjones.udri

1
Це для локальної установки. Наприклад, зробити такий швидкий знімок. Так, існує ризик безпеки, якщо те саме стосується інших середовищ, що розгортаються. Для місцевих жителів я вважаю, що це не так. "Однак ви повинні обмежити своє походження у випадку інших середовищ, таких як stage, prod"
smsivaprakaash

12

Це працювало для мене:

npm install -g local-cors-proxy

Кінцева точка API, яку ми хочемо запитати, яка має проблеми з CORS:

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

Запустити проксі:

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

 Proxy Active 

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

Потім у вашому клієнтському коді нова кінцева точка API:

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

Кінцевим результатом буде запит на https://www.yourdomain.ie/test/list без проблем CORS!


Будь ласка, переконайтесь, що сервер працює паралельно, як відкрийте нове вікно підказки cmt та запустіть код lcp --proxyUrl yourdomain.com
Govarthanan Venunathan

8

Я знаю, що це старіша публікація, але я виявив, що мені вдалося виправити цю помилку, використовуючи IP-адресу мого сервера, а не доменне ім’я в моєму запиті на отримання. Так наприклад:

#(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

Якщо ви використовуєте nginx, спробуйте це

#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

Перегляньте https://expressjs.com/en/resources/middleware/cors.html Ви повинні використовувати cors.

Встановити:

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

Ви повинні помістити цей код на свій сервер вузлів.


1
Як ви можете дізнатись, чи це сервер OP, і він написаний у NodeJs?
Марек Шкудельський

Якщо ви створили сервер вузлів (режим розробки), ви можете використовувати цей метод, щоб використовувати вибірку в js.
Ернерсто Пасторі,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.