CORS: Не можна використовувати підстановку в Access-Control-Allow-Origin, коли прапор облікових даних є істинним


295

У мене налаштування за участю

Frontend-сервер (Node.js, домен: localhost: 3000) <---> Backend (Django, Ajax, домен: localhost: 8000)

Браузер <- webapp <- Node.js (Обслуговувати додаток)

Веб-переглядач (webapp) -> Ajax -> Django (Обслуговування ajax POST-запитів)

Тепер моя проблема полягає в налаштуванні CORS, який webapp використовує для здійснення Ajax дзвінків на сервер бекенда. У хромі я продовжую отримувати

Неможливо використовувати підстановку в Access-Control-Allow-Origin, коли прапор облікових даних є істинним.

також не працює на Firefox.

Моя настройка Node.js:

var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', 'http://localhost:8000/');
    res.header('Access-Control-Allow-Credentials', true);
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
};

І в Django я використовую це програмне забезпечення разом з цим

Вебппп робить запити як такі:

$.ajax({
    type: "POST",
    url: 'http://localhost:8000/blah',
    data: {},
    xhrFields: {
        withCredentials: true
    },
    crossDomain: true,
    dataType: 'json',
    success: successHandler
});

Отже, заголовки запитів, які надсилає web-сайт, виглядають так:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"
Access-Control-Allow-Methods: 'GET,PUT,POST,DELETE'
Content-Type: application/json 
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Cookie: csrftoken=***; sessionid="***"

І ось заголовок відповіді:

Access-Control-Allow-Headers: Content-Type,*
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE
Content-Type: application/json

Де я помиляюся ?!

Редагувати 1: Я використовував chrome --disable-web-security, але тепер хочу, щоб фактично працювали.

Редагувати 2: Відповідь:

Отже, рішення для мене django-cors-headersконфігурація:

CORS_ORIGIN_ALLOW_ALL = False
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = (
    'http://localhost:3000' # Here was the problem indeed and it has to be http://localhost:3000, not http://localhost:3000/
)

1
Для мене це localhost: 3000 без http, як це: CORS_ORIGIN_WHITELIST = ('localhost: 3000',)
Андрій

Ви маєте на увазі, що використовуєте розробку фронтенду та бекенда в одному ПК?
fanhualuojin154873

як щодо фронтену та бекенда в різних ПК?
fanhualuojin154873

@ixaxaar, чому ти кажеш, що http працює для тебе? всі ми лише "локальний господар: 3000" працює.
244бой

@ 244boy Так, справа не в тому http, це /в кінці. Я вважаю, що пропуск http може спрацювати, але я над цим роком не працював кілька років, тому не знаю, що зараз працює!
ixaxaar

Відповіді:


247

Це частина безпеки, ви не можете цього зробити. Якщо ви хочете дозволити облікові дані, ви Access-Control-Allow-Originне повинні використовувати їх *. Вам доведеться вказати точний протокол + домен + порт. Для ознайомлення див. Ці питання:

  1. Піддомени, порти та протоколи підключення підключення підключення доступу, контроль та дозвіл
  2. Перехресне походження ресурсів з використанням облікових даних

Крім того *, занадто дозвільне і може перешкодити використанню облікових даних. Так встановити http://localhost:3000або http://localhost:8000як дозволити вихідний заголовок.


45
Але що робити, якщо існує більше одного домену?
aroth

13
@aroth Ви можете надати список доменів. Пов'язані питання: stackoverflow.com/questions/1653308 / ...
user568109

13
@ user568109 Чи можете ви пояснити, "Крім того, *це занадто дозвільне і може перешкодити використанню облікових даних."?
Хуго Вуд

12
Що таке "точний домен", якщо запит надходить з мобільного пристрою, як це може статися з Кордовою?
Крістіан

8
@Christian старий, але якщо комусь все ще цікаво, ця проблема трапляється лише для програм, що працюють у браузерах, оскільки ця помилка перекидається браузером з міркувань безпеки. У інших клієнтів, таких як мобільний додаток, листоноша або будь-який інший код, який використовує http-клієнт, щоб зробити запит, не виникне цієї проблеми, тому вам не доведеться турбуватися про походження та точний домен .
Еліссон

32

Якщо ви використовуєте проміжне програмне забезпечення CORS і хочете надіслати withCredentialбулеву true, ви можете налаштувати CORS так:

var cors = require('cors');    
app.use(cors({credentials: true, origin: 'http://localhost:3000'}));

16

Якщо ви користуєтесь, expressви можете використовувати пакет cors, щоб дозволити CORS подібним чином замість того, щоб писати проміжне програмне забезпечення;

var express = require('express')
, cors = require('cors')
, app = express();

app.use(cors());

app.get(function(req,res){ 
  res.send('hello');
});

12
Ага, зараз це зручніше, однак результат той самий :( BTW, я використовуюapp.use(cors({credentials: true}));
ixaxaar

1
Можливо, ви захочете ознайомитись із цим тестуваним програмним забезпеченням Django CORS.
Булкан

1
Отже, у вас є два середніх предмета Django? Я б використовував лише django-cors-headerдодаток. Переконайтеся, що ви додали localhost до CORS_ORIGIN_WHITELISTналаштування та встановили CORS_ALLOW_CREDENTIALSзначенняTrue
Bulkan

1
Так людина, намагався перш ніж без толку, було CORS_ORIGIN_ALLOW_ALL = True, CORS_ORIGIN_WHITELIST = ( 'localhost' )і CORS_ALLOW_CREDENTIALS = True я отримую ці заголовки:Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: http://localhost:3000/ Access-Control-Allow-Methods: POST,GET,OPTIONS,PUT,DELETE Content-Type: application/json
ixaxaar

5
Прочитавши цю документацію: github.com/expressjs/corsuse я використовую цей конфігурацію: app.use (cors ({облікові дані: true, походження: ' localhost: 3001 '})); працює на мене.
алл

11

Спробуй це:

const cors = require('cors')

const corsOptions = {
    origin: 'http://localhost:4200',
    credentials: true,

}
app.use(cors(corsOptions));

6

Якщо ви хочете дозволити всі джерела і зберегти ідентифікаційні дані, це працювало для мене:

app.use(cors({
  origin: function(origin, callback){
    return callback(null, true);
  },
  optionsSuccessStatus: 200,
  credentials: true
}));

@TSlegaitis Ха-ха, так, це працює для всіх джерел, але зберігає дані. Я б не рекомендував його для безпеки, але він працює.
Squirrl

2

(Редагувати) Попередньо рекомендований додаток більше не доступний, ви можете спробувати цей інший


Для розробки в Chrome, встановлення цього додатка позбудеться певної помилки:

Access to XMLHttpRequest at 'http://192.168.1.42:8080/sockjs-node/info?t=1546163388687' 
from origin 'http://localhost:8080' has been blocked by CORS policy: The value of the 
'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' 
when the request's credentials mode is 'include'. The credentials mode of requests 
initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

Після встановлення переконайтеся, що ви додали свій шаблон URL-адреси Intercepted URLs, натиснувши на значок AddOn ( CORS , зелений або червоний) та заповнивши відповідне текстове поле. Приклад шаблону URL-адреси, який слід додати тут, буде http://localhost:8080:*://*


Я отримав це тільки після його встановлення, якісь ідеї?
Джаліл

Це працювало для мене. Попередження, якщо у вас є інші подібні додатки, вам слід видалити його, перш ніж спробувати цей.
FilippoG

виправте пошкоджене посилання
Лук Арон

Здається, що оригінальне додавання було видалено, я додав нову рекомендацію як (Правка) вгорі
Еріель Марімон

1

Це працює для мене в розвитку, але я не можу порадити, що у виробництві це просто інший спосіб виконання роботи, про який не було сказано, але, мабуть, не найкращий. Все одно:

Ви можете отримати походження з запиту, а потім використовувати його у заголовку відповіді. Ось як це виглядає в експресі:

app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Origin', req.header('origin') );
  next();
});

Я не знаю, як це могло б виглядати з вашим налаштуванням python, але це слід легко перекласти.


Документи Mozilla Dev розширюють ідею зміни дозволеного походження на те, що використовується у запиті. Пропонується додати заголовок відповіді HTTP "Варіант: Походження" та дозволені домени.
Рамзіс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.