Рекомендуемое решение для кодов ошибок AJAX, CORS, Chrome & HTTP (401,403,404,500)
Фон
(Если вы знакомы с CORS, вы можете перейти к Вопрос в конце)
CORS [1] - это решение, позволяющее браузерам разрешать доступ к ресурсам из разных доменов. Например. REST с использованием AJAX.
В Интернете хорошо видно, что Chrome (и друзья Webkit) не обрабатывают запросы HTTP-аутентификации, когда такой ресурс требует этого. Например. [2]
(это означает, что браузер не показывает диалоговое окно входа в систему, например, страницу входа в систему Web-Mail при сбое загрузки тегов изображений с использованием 401 и требует учетных данных. Пользователь может быть обманут для ввода своих учетных данных электронной почты)
В этой ситуации поведение Chrome - это отбросить ответ, почти полностью отменив запрос.
Фактически, Chrome только разрешит ответ нормально, если произойдет 200; любой другой код состояния проглатывается, а вызов AJAX прерывается.
Если для выполнения запроса Ajax используется jQuery, а удаленный сайт отвечает кодом состояния HTTP 401, запрос отменяется, а ajax завершается с ошибкой, но код 401 отсутствует. Это как будто соединение сработало или проблема с эквивалентным нижним уровнем.
Единственный веб-сайт, который я видел, который упоминает это предостережение CORS, - это [1]
Браузеры не очень хорошо сообщают, что пошло не так, когда произошла ошибка. Например, Firefox сообщает о статусе 0 и пустой statusText для всех ошибок. Браузеры также сообщают об ошибке в журнал консоли, но это сообщение недоступно из JavaScript. Когда вы работаете с атеррором, вы узнаете, что произошла ошибка, но не больше.
Вы можете отключить эту безопасность, используя флаг запуска Chrome - только для проверки функционирования бэкэнд работает "нормально", и одно здравомыслие не было подвержено чрезмерному воздействию потери правильных кодов состояния. См. [2]
Проблема
Что делать, если клиентский код бэкэнд и front-end должен использовать 401 как часть процесса аутентификации? - любые сбои просто искажены в один вывод ошибки.
Например: после выдачи запроса на аутентификацию - например, 2-точечный запрос токена OAuth -актив бэкэнд RESTful, который использует соответствующие коды состояния. Клиент не имеет понятия, если:
- 401 Пользователь не прошел аутентификацию.
- --- Не удалось выполнить соединение.
- 400 Был неправильный запрос.
- 500 У сервера возникли проблемы.
- 207 После успеха не было контента.
Бэкэнд из нашего, который был написан довольно ОТДЫХ, следуя за множеством передовых методов, которые в то время считались экономически эффективными; один из них полагался на соответствующие коды состояния HTTP.
Клиент Java REST, с которым мы работаем, отлично поработал.
Теперь я начал создавать Javascript-клиент для встраивания в веб-страницы - в частности, с помощью CORS, и мы столкнулись с проблемой в Chrome и т.д. (Примечание: Firefox кажется прекрасным, и в настоящее время мы вообще не заботимся об IE).
Вопрос
Что люди сделали для решения этих проблем?
Есть ли что-то, что можно сделать, чтобы сделать CORS более подходящим для доверенных бэкэндов?
Ссылки
Ответы
Ответ 1
Теперь, после долгих ворчаний, мне удалось заставить его работать. румяна
Кажется, что очень много вуду, которое составляет точный сценарий, который гарантирует, что CORS будет работать в каждом браузере, однако, проследив многочисленные проблемы, такие как:
- Nginx по умолчанию использует только HTTP/1.0 в обратном прокси-сервере по умолчанию
- Tomcat молча игнорирует двойную декларацию init-param с тем же ключом, но причал объединяет их (поэтому фильтр CORS был отключен на сервере, но включен в dev-laptop), а nginx перезаписывал некоторые заголовки.
Наткнувшись на то, что казалось полным полным, я закончил писать обертку CORS 4xx- > 200 как плагин jquery, пытаясь решить проблему. Отладка этого плагина привела меня к моему окончательному исправлению.
Ответ 2
Просто столкнулся с этой проблемой. Настройка заголовков HTTP для ответа 401 сделала трюк для меня. Библиотека, которую я использовал, не делала это правильно без какой-либо настройки. например:.
self.headers["Access-Control-Max-Age"] = '1728000'
self.headers["Access-Control-Allow-Origin"] = "http://localhost:3001"
self.headers["Access-Control-Allow-Methods"] = "ANY"
self.headers["Access-Control-Allow-Credentials"] = 'true'