Проверьте, применяется ли такая же политика происхождения - PullRequest
24 голосов
/ 23 февраля 2012

Есть ли "безопасный" способ проверить, применяется ли такая же политика происхождения к URL-адресу, перед тем, как пытаться использовать методы ajax? Вот что у меня есть:

function testSameOrigin(url) {

    var loc = window.location,
        a = document.createElement('a');

    a.href = url;

    return a.hostname == loc.hostname &&
           a.port == loc.port &&
           a.protocol == loc.protocol;
}

Это работает, но это своего рода ручное предположение, основанное на статье википедии . Есть ли лучший способ предварительной проверки междоменного разрешения? JQuery можно использовать.

Ответы [ 5 ]

15 голосов
/ 05 марта 2012

Существует ли "безопасный" способ проверить, применяется ли такая же политика происхождения к URL-адресу, перед тем, как пытаться использовать методы ajax?Вот что у меня есть:

function testSameOrigin(url) {

    var loc = window.location,
        a = document.createElement('a');

    a.href = url;

    return a.hostname == loc.hostname &&
           a.port == loc.port &&
           a.protocol == loc.protocol;
}

Это безопасный и надежный способ сделать это, если вы делаете (или, скорее, не делаете) определенные вещи.

Этот вид работает, но это своего рода ручное предположение, основанное на статье в Википедии.

Это должно полностью работать при "нормальных" обстоятельствах.Его нужно будет изменить, если вы планируете использовать междоменный сценарий .

Если вы измените document.domain в своих сценариях, например, с "foo.example.com" иОт "bar.example.com" до "example.com" ваша функция testSameOrigin вернет false для "http://example.com",, где на самом деле она должна вернуть true.

Если выЕсли вы планируете изменить document.domain, вы можете просто добавить проверку для этого в своем скрипте.

Если вы планируете использовать CORS (см. ссылку выше), чтобы разрешить междоменную связь, он также вернетложный минус. Но если вы используете CORS, у вас будет список доменов, с которыми вы можете общаться, и вы также можете добавить этот список в эту функцию.

Есть ли лучший способпредварительной проверки междоменного допуска? jQuery можно использовать.

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

Предполагая, что вы не связываетесь с document.domain или не используете CORS, ваше оригинальное решение, вероятно, лучше, поскольку ему не нужно делать дополнительный запрос, чтобы определить, доступен ли сервер или нет.Даже если вы выполняете некоторые междоменные сценарии, вам, вероятно, лучше всего изменить имеющуюся сейчас функцию.

8 голосов
/ 01 марта 2012

Интересный вопрос! Я искал вокруг и не мог найти ничего, кроме того, что вы опубликовали, но я столкнулся с этим, когда возился с некоторым тестовым кодом. Если вам нужен простой способ протестировать URL-адрес без запроса, я бы сделал это так, как вы. Если вам не нужно отправлять запрос на тестирование, попробуйте следующее:

Сделайте простой запрос ajax на любой URL, который вы хотите:

var ajaxRequest = $.ajax({
  url: 'http://www.google.com',
  async: false
});

, который возвращает jqXHR объект, который вы затем можете проверить:

ajaxRequest.isRejected(); // or...
ajaxRequest.isResolved();

Теперь единственная проблема с этим заключается в том, что isRejected() будет оцениваться до true для каждого отдельного случая, когда страница не загружается (т. Е. 404 Not Found и т. Д.), Но вы можете проверить код состояния с помощью :

ajaxRequest.status;

Похоже, что приведенная выше строка вернет 0, когда вы попытаетесь нарушить ту же политику происхождения, но в других случаях вернет соответствующий код ошибки (т.е. 404).

Итак, чтобы подвести итог, возможно, вы могли бы попробовать сделать что-то вроде:

function testSameOrigin(testUrl) {

  var ajaxRequest = $.ajax({
    url: testUrl,
    async: false
  });

  return ajaxRequest.isRejected() && ajaxRequest.status === 0;
}

Ни в коем случае не окончательный ответ, но я надеюсь, что он поможет вам понять, что вы ищете!

2 голосов
/ 26 января 2015

Попробуйте также это решение.

function csrfSafeMethod(method) {
  // these HTTP methods do not require CSRF protection
  return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

function sameOrigin(url) {
  // test that a given url is a same-origin URL
  // url could be relative or scheme relative or absolute
  var host = window.document.location.host; // host + port
  var protocol = window.document.location.protocol;
  var srOrigin = '//' + host;
  var origin = protocol + srOrigin;
  // Allow absolute or scheme relative URLs to same origin
  return (url === origin || url.slice(0, origin.length + 1) === origin + '/') ||
    (url === srOrigin || url.slice(0, srOrigin.length + 1) === srOrigin + '/') ||
    // or any other URL that isn't scheme relative or absolute i.e relative.
    !(/^(\/\/|http:|https:).*/.test(url));
}

// if you want to check before you make a call
if (!csrfSafeMethod(data.type) && sameOrigin(data.url)) {
  // ...
}

// or if you want to set csrf token
$.ajax({
  beforeSend: function (xhr, settings) {
    if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
      xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
    }
  }
});
0 голосов
/ 08 июля 2014

Опираясь на ответ Дагг Наббит, это кажется немного более полным:

function sameOrigin(url) {
    var loc = window.location, a = document.createElement('a')
    a.href = url

    return a.hostname === loc.hostname &&
           a.port === loc.port &&
           a.protocol === loc.protocol &&
           loc.protocol !== 'file:'
}

Предостережения, о которых я могу думать:

  • не учитывает document.domain
  • не учитывает CORS
  • Не работает в IE7 (как упомянуто в zanona)
  • Не работает в странных средах (например, Android), где вы можете получить доступ к произвольным file:// протокольным путям (кто-то, пожалуйста, проверьте это, информация об Android может быть устаревшей https://security.stackexchange.com/questions/25138/same-origin-policy-for-file-urls-in-android-browser)
0 голосов
/ 29 февраля 2012

Другой способ выполнения междоменного сценария - использование JSON-P .Вы также можете прочитать эту статью .В противном случае междоменный сценарий не разрешен той же политикой происхождения.

...