Учетные данные CORS cookie из мобильного WebView загружаются локально с файлом://
Потерпите меня, вам нужно немного объяснения.
Я помогаю построить гибридное мобильное веб-приложение. Основной кодовой базой является HTML5 и JavaScript, которые будут обернуты в собственный мобильный веб-просмотр (a la Phonegap).
Частичная функциональность требует, чтобы приложение отправляло информацию в веб-службу, контролируемую одним из наших клиентов. Существует очень мало возможностей для изменения этого веб-сервиса, поскольку он используется другими. Мы отправляем JSON с помощью HTTP POST и получаем ответы с сервера. Часть этого ответа представляет собой файл cookie JSESSIONID, который управляет нашей сессией с сервером. После первоначального вызова initSession()
нам необходимо отправить файл cookie JSESSIONID с каждым запросом (AJAX).
При развертывании на мобильном устройстве веб-приложение завершается в собственном веб-представлении, которое запускает веб-приложение, просматривая file:///path/to/app/index.html
.
Первое, что мы попробовали, - попросить нашего клиента установить Access-Control-Allow-Origin: *
в заголовке ответа, чтобы разрешить CORS. Затем мы попытались отправить сообщение на сервер:
$.ajax({
url: 'http://thirdparty.com/ws',
data: data,
type: "POST",
dataType: "JSON",
success: successCallback,
error: failedCallback
});
Наблюдая за запросами, было очевидно, что файлы cookie не включены. При ближайшем рассмотрении есть специальный раздел в спецификации CORS для учета учетных данных пользователя, который включает файлы cookie сеанса. Поэтому я изменил вызов AJAX, чтобы включить это:
$.ajax({
url: 'http://thirdparty.com/ws',
data: data,
type: "POST",
dataType: "JSON",
success: successCallback,
error: failedCallback,
xhrFields { withCredentials: true }
});
Другая ошибка, на этот раз из браузера. Более подробное чтение дало следующее:
Если сторонний сервер не ответил заголовком Access-Control-Allow-Credentials: true
, ответ будет проигнорирован и не будет доступен для веб-контента.
Важное примечание: при ответе на запрашиваемый запрос сервер должен указать домен в заголовке Access-Control-Allow-Origin
и не может использовать wild carding.
Поэтому нам нужно изменить заголовки серверов, чтобы включить Access-Control-Allow-Credentials: true
и Access-Control-Allow-Origin
в наш Origin.
Здесь мы, наконец, приходим к моей проблеме: при загрузке веб-страницы с использованием протокола file://, заголовок запроса Origin
, отправленный из веб-представления, установлен на null
. Поэтому он не может быть проанализирован сервером, поэтому сервер не может установить его в Access-Control-Allow-Origin
. Но если сервер не может установить Access-Control-Allow-Origin
на нечто иное, чем *
, мы не можем отправлять учетные данные, включая файлы cookie.
Итак, я застрял. Что делать? Я видел аналогичный вопрос, размещенный здесь, но я не совсем понимаю предлагаемый ответ. Любая помощь приветствуется!
Ответы
Ответ 1
Я понимаю, что этот вопрос устарел, но я подумал, что все равно набросись на него. В случае запросов CORS браузер запускает их. Это означает, что - несмотря на любой метод $.ajax()
, который вы используете, на сервер отправляется запрос OPTIONS
.
В этом предпродажном запросе OPTIONS
говорится:
"Эй, чужой сервер-от-другого-домена, я хочу отправить вам непростой запрос (простой запрос не предваряется). Мой непростой запрос будет иметь такие заголовки и тип контента и т.д. Можете ли вы сообщить мне, если все в порядке?"
Затем сервер будет делать все, что он делает (возможно, проверяет какую-либо конфигурацию или базу данных) и отвечает разрешенным источником (-ами), допустимым заголовком (-ами) и/или допустимым (ыми) методом (-ами).
Наконец - если этот запрос preflight OPTIONS
получил ответ, который позволяет фактическому методу $.ajax()
идти - он идет.
CORS не то же самое, что JSONP.
Все сказанное - в то время как withCredentials
успех перед полетом требует ответа на перенос заголовка Access-Control-Allow-Credentials
(как указано в вопросе), то есть IN ДОБАВЛЕНИЕ к значениям Access-Control-Allow-Origins
И Access-Control-Allow-Methods
, которые должны включать в себя грани от предполагаемого запроса.
Например, если вы делаете запрос CORS POST
из источника http://foo-domain.com
с заголовками somevalue
до http://bar-domain.com
, запрос preflight OPTIONS
погаснет и для того, чтобы фактический пост-запрос был сделанный в http://bar-domain.com
, запрос OPTIONS
должен был бы получить ответ со значением Access-Control-Allow-Origins
, который включал http://foo-domain.com
. Это может быть имя самого начала или *
. Ответ также должен иметь значение Access-Control-Allow-Methods
, которое включало POST
. Это также может быть *
. И, наконец, если мы хотим, чтобы наш заголовок somevalue
был разрешен, ответ должен содержать значение Access-Control-Allow-Headers
, которое включает наш заголовок somevalue
или *
.
Чтобы повернуть назад - если вы не можете управлять сервером или не имеете возможности разрешить серверу разрешать ваши запросы CORS, вы всегда можете использовать JSONP или некоторый тип urlEncoded и/или делать простые запросы без пользовательских заголовков. GET
, HEAD
, а полные запросы POST
обычно являются простыми запросами.
Ответ 2
Я предполагаю, что если вы создаете гибридное приложение, вы используете кордову. Если это так, вам не нужно CORS, вам просто нужно, чтобы белый список доменов, к которым вы хотите получить доступ.
http://docs.phonegap.com/en/3.0.0/guide_appdev_whitelist_index.md.html
Ответ 3
Мое предложение установлено ACCESS-CONTROL-ALLOW-ORIGIN
на null
на стороне сервера
Да, этот вопрос меня немного беспокоит.
Относительно CORS spec, null
может удовлетворить ситуацию, когда запрос CORS из схемы file://
И пратическая рекомендация по этой спецификации заключается в том, чтобы установить ее как origin-list-or-null, которая является либо списком пространственно- разделенное происхождение или просто "нуль" (кстати, строка %x6E %x75 %x6C %x6C
из определения для origin-list-or-null
буквально null
hex-encoded)
Наконец, вы спросите, не будет ли это равным *
, если мы установим ACCESS-CONTROL-ALLOW-ORIGIN
в null
, так как каждый запрос из схемы file://
действителен (это означает, что каждое гибридное приложение может получить доступ к вашей конечной точке, если оно знает о вашем URI)?
Ну, учитывая Access-Control-Allow-Credentials: true
, я считаю, что на сервере работает целый механизм аутентификации. Он должен был отфильтровать эти запросы без правильного авторизации
Надеюсь, что это поможет
Ответ 4
Попробуйте посмотреть на www.5app.co.uk. Исключает использование вызовов XHR в целом и надежно работает на мобильных устройствах, когда происходит соединение данных. Затем Gateway взаимодействует с вашим клиентом.
Ответ 5
Использовать запрос JsonP. Запрос JsonP позволяет выполнять запрос перекрестного домена. Вот пример.