Как сделать XMLHttpRequest кросс-домен с помощью Credentials, авторизацией HTTP (CORS)?

Я не могу выполнить кросс-доменный запрос с заголовком авторизации (тестирование с помощью Firefox). У меня есть запросы, работающие без аутентификации, но как только я установил withCredentials в true, я больше не могу читать ответ с сервера.

На сервере я отправляю эти заголовки (используя метод after_request в Flask):

resp.headers['Access-Control-Allow-Origin'] = '*'
resp.headers['Access-Control-Allow-Credentials'] = 'true'
resp.headers['Access-Control-Allow-Methods'] = 'POST, OPTIONS'
resp.headers['Access-Control-Allow-Headers'] = 'Authorization'

Никакой вызов OPTIONS на самом деле не выполняется Firefox. На клиенте я вызываю вызов XMLHttpRequest:

var xhr = new XMLHttpRequest()
xhr.open( 'POST', 'http://test.local:8002/test/upload', true)
xhr.withCredentials = true
xhr.onreadystatechange = function() {
    console.log( xhr.status, xhr.statusText )
}
xhr.send(fd)

Без withCredentials установить оператор журнала будет записывать ожидающую информацию на консоль. Как только я установил значение, однако xhr не разрешает доступ, и я просто пишу значение 0 и пустую строку. Я не задал здесь заголовок авторизации, но это не должно повлиять на мою способность читать результат.

Если я попытаюсь добавить имя пользователя/пароль в команду "open", я получаю ошибку NS_ERROR_DOM_BAD_URI: Access to restricted URI denied.

Что я делаю неправильно?

Ответ 1

Я написал статью с полной настройкой CORS.

Я нашел несколько проблем, которые могут привести к этой проблеме:

  • Access-Control-Allow-Origin не может быть подстановочным знаком, если используются учетные данные. Проще всего просто скопировать заголовок Origin запроса в это поле. Непонятно, почему стандарт запрещает шаблон.
  • Firefox кэширует результаты Access-Control, даже если вы очищаете кеш (возможно, для сеанса). Перезапуск заставил его выполнить новый запрос OPTIONS. Чтобы помочь в отладке, я добавил заголовок Access-Control-Max-Age: 1
  • Имя пользователя/пароль для команды open, по-видимому, не используется в качестве учетных данных. Вы должны добавить заголовок Authorization самостоятельно. xhr.setRequestHeader( 'Authorization', 'Basic ' + btoa( user + ':' + pass ) )

В целом система withCredentials является довольно braindead. Легче просто написать сервер, который принимает авторизацию как часть тела запроса.