Обратный вызов JSONP не выполняется при запуске на локальном хосте

StackOverflow https://stackoverflow.com/questions/1217926

Вопрос

Это странно, мне было интересно, если кто-нибудь мог бы пролить свет на то, почему это произошло.

По сути, я старался изо всех сил пытаться протестировать JSONP, чтобы я мог реализовать веб-сервис JSON, который могут использовать другие сайты. Я занимаюсь разработкой на локальном хосте - в частности, на Visual Studio 2008 и на встроенном веб-сервере Visual Studio 2008.

Итак, в качестве теста JSONP с jQuery я реализовал следующее:

$().ready(function() {
  debugger;
  try {
    $.getJSON("<%= new Uri(Request.Url, "/").ToString() %>XssTest?callback=?", function(data) {
        alert(data.abc);
    });
  } catch (err) {
    alert(err);
  }
});

И на сервере ..

<%= Request["callback"] %>({abc : 'def'})

Итак, в конечном итоге я устанавливаю точку останова на сервере и получаю точку останова как в первом " отладчике; " statment в скрипте на стороне клиента и на сервере. URL JSONP действительно вызывается после загрузки страницы. Это отлично работает.

У меня была проблема с тем, что обратный вызов никогда не будет выполнен. Я проверял это как в IE8, так и в Firefox 3.5. Ни один из них не вызвал бы обратный вызов. Улов (err) также никогда не был достигнут. Ничего не случилось вообще!

Я застрял на этой неделе и даже протестировал HTTP-запрос с ручным ключом в Telnet на указанном порту, чтобы убедиться, что сервер возвращает формат ...

callbackfn({abc : 'def'})

.. и это так.

Затем меня осенило, что если я изменю имя хоста с локального на локальный с помощью глобализатора ('.'), то есть http://localhost.:41559/ вместо http: // localhost: 41559 / (да, добавление точки к любому имени хоста допустимо, именно для DNS то, что global:: для пространств имен C #). И тогда это сработало! Internet Explorer и Firefox 3.5 наконец-то показали мне предупреждающее сообщение, когда я только что добавил точку.

Так что это заставляет меня задуматься, что здесь происходит? Почему поздняя генерация тегов скрипта будет работать с именем хоста в Интернете, а не с простым localhost? Или это правильный вопрос?

Очевидно, это реализовано в целях безопасности, но что они пытаются обезопасить? И, заставив его работать с точкой, я только что обнаружил дыру в безопасности в этой функции безопасности?

Кстати, мой файл hosts, хотя и изменен для других хостов, не имеет ничего особенного с localhost; 127.0.0.1 / :: 1 по умолчанию все еще на месте без переопределений ниже.

ПОСЛЕДУЮЩАЯ ИНФОРМАЦИЯ . Я прошел мимо этого для целей местного развития, добавив:

127.0.0.1   local.mysite.com

.. в мой файл hosts, затем добавьте следующий код в мой global.asax:

protected void Application_BeginRequest(object sender, EventArgs e)
{
    if (Request.Headers["Host"].Split(':')[0] == "localhost")
    {
        Response.Redirect(
            Request.Url.Scheme
            + "://"
            + "local.mysite.com"
            + ":" + Request.Url.Port.ToString()
            + Request.Url.PathAndQuery
            , true);
    }
}
Это было полезно?

Решение

Я собираюсь выбросить ответ там; после некоторой мысли я пришел к своим собственным выводам.

Возможно, это функция безопасности, которая реализована для того, чтобы помешать веб-сайту в Интернете вызывать службы JSONP, работающие на клиентском компьютере.

Веб-сайт может просто просмотреть список портов и продолжать вызывать localhost для разных портов и путей. «Локальный хост» - это одно из немногих имен хостов DNS, которые имеют динамическое значение в зависимости от того, когда и где он запрашивается, делая потенциальные цели уязвимыми. И да, тот факт, что добавление точки (.) К 'localhost' ('localhost.') Приводит к работающему обходному пути, обнажает уязвимость безопасности, но предлагает [предварительный] обходной путь для целей разработки.

Лучшим подходом является сопоставление петлевого IP-адреса с новой записью имени хоста в файле hosts, чтобы он работал локально, не был подвержен " fixed " обновлением браузера и не работает нигде, кроме как на рабочей станции разработки.

Другие советы

У меня похожая проблема. Большинство решений, которые я пробовал, работают с IE (7), но мне трудно заставить Firefox (3.5.2) играть в мяч.

Я установил HttpFox, чтобы увидеть, как ответы моего сервера интерпретируются на клиенте, и я получаю NS_ERROR_DOM_BAD_URI. Моя ситуация немного отличается от вашей, хотя я пытаюсь вызвать обратный вызов JSONP на тот же сайт, с которого пришла страница хостинга, а затем этот вызов отвечает перенаправлением 302 на другой сайт. (Я использую перенаправление в качестве удобного способа вернуть файлы cookie с обоих доменов в браузер.)

Я использую jQuery и изначально пытался сделать стандартный вызов AJAX через $ .ajax (). Я подумал, что поскольку первоначальный запрос был на тот же сайт, что и на странице хостинга, Firefox просто следовал за ответом 302 на другой домен. Но нет, похоже, это было нарушением защиты XSS. (Обратите внимание, что вопреки тому, что подразумевает возврат перенаправления в ответ на запрос XHR jQuery следует перенаправлению 302 для стандартного dataType = " json " вызов: перенаправление в тот же домен работает нормально; перенаправление в другой домен генерирует NS_ERROR_DOM_BAD_URI в браузере.) Я не понимаю, почему перенаправления того же домена 302 на другие домены не могут быть просто отслежены - в конце концов, именно домен страницы хостинга выполняет перенаправление, так почему ему нельзя доверять? Если вас беспокоят атаки с использованием сценариев, тогда маршрут JSONP в любом случае открыт для злоупотреблений ...

jQuery's $ .getJSON () с? callback =? суффикс также терпит неудачу в Firefox с той же ошибкой. Как и использование $ .getScript () для прокрутки моего собственного JSONP & Lt; script & Gt; тег.

То, что работает, имеет предварительно существующий < script id = " jsonp " & Тип = Quot; текст / JavaScript Quot &; GT &; Л &; & / Скрипт GT; в HTML, а затем с помощью $ (" jsonp "). attr (" src " ;, url + "? callback = myCallback " ;) чтобы вызвать вызов JSONP. Если я это сделаю, то будет выполнено междоменное перенаправление 302, и я передам свой ответ JSON в myCallback (который я определил одновременно с тегом & Lt; script / & Gt;).

И да, я разрабатываю все это, используя Cassini с URL-адресами localhost: порт . Кассини не будет отвечать на URL, не относящиеся к локальному хосту, поэтому я не могу с легкостью попробовать local.mysite.com, чтобы посмотреть, как это повлияет на решения, которые я пробовал выше. Однако прикрепление точки в конце localhost, похоже, решило все мои проблемы!

Теперь я могу вернуться к стандартному вызову $ .ajax ({... dataType: " jsonp " ...}) с localhost __.__: порт вместо localhost: порт и все хорошо. Мне интересно, что изменение атрибута src тега сценария, который уже существует в HTML делает страницы, позволяет вызывать обычные локальные URL-адреса. .

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top