检查是否适用相同的原始政策

时间:2012-02-22 23:17:58

标签: javascript jquery ajax cross-domain cross-domain-policy

在实际尝试使用ajax方法之前,是否有“安全”方法检查相同的原始策略是否适用于URL?这就是我所拥有的:

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;
}

这种作品,但它是基于wikipedia article的手动猜测。有没有更好的方法来预先检查跨域允许? jQuery可以使用。

5 个答案:

答案 0 :(得分:15)

  

在实际尝试使用ajax方法之前,是否有“安全”方法检查相同的原始策略是否适用于URL?这就是我所拥有的:

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;
}

这是一种安全可靠的方式,只要您正在做(或者更确切地说不做)某些事情。

  

这种作品,但它是基于维基百科文章的手动猜测。

这应该在“正常”情况下完全奏效。如果您打算使用cross-domain scripting,则需要进行修改。

如果在脚本中修改document.domain,例如从“foo.example.com”和“bar.example.com”修改为“example.com”,则testSameOrigin函数将返回{{ 1}}代表“http://example.com”,实际上它应该返回false

如果您打算修改true,可以在脚本中添加一个支票。

如果您计划使用CORS(请参阅上面的链接)以允许跨域通信,它也将返回错误否定。但是如果您使用的是CORS,则会有一个可以与之通信的域列表,您也可以将该列表添加到此函数中。

  

是否有更好的预先检查跨域允许的方法? jQuery可以使用。

可能不是,虽然可能值得一提的是,你在Steve的答案中看到的那个问题可能是“观察者的困境”......那些错误看起来就像是控制台试图检查另一个窗口造成的,不一定来自剧本。

假设您没有使用document.domain或使用CORS,原始解决方案可能更好,因为它不需要额外请求来确定服务器是否可用。即使您正在进行一些跨域脚本编写,修改现在可以容纳它的功能可能是您最好的选择。

答案 1 :(得分:8)

有趣的问题!我四处搜索,除了你发布的内容之外找不到任何东西,但是当我搞乱一些测试代码时,我确实遇到了这个问题。如果您只是想要一种简单的方法来测试URL而不需要请求,我就会按照您的方式进行操作。如果您不关心提出测试请求,可以试试这个:

向您想要的任何网址发出简单的ajax请求:

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

返回一个jqXHR对象,然后您可以检查:

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

现在,唯一的问题是,isRejected()将针对页面未加载的每个案例(即404 Not Found等)评估为true,但您可以检查状态代码:

ajaxRequest.status;

当您尝试破坏相同的原始策略时,上面的行似乎会返回0,但在其他情况下它将返回相应的错误代码(再次,即404)。

总而言之,也许你可以尝试做类似的事情:

function testSameOrigin(testUrl) {

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

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

无论如何都不是一个明确的答案,但我希望它可以帮助你弄清楚你在寻找什么!

答案 2 :(得分:2)

尝试此解决方案。

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"));
    }
  }
});

答案 3 :(得分:0)

执行跨域脚本的另一种方法是使用JSON-P。 您还可以阅读此article。 否则,相同的源策略不允许跨域脚本编写。

答案 4 :(得分:0)

建立Dagg Nabbit的答案,这似乎有点完整:

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所述)
  • 可以访问任意file://协议路径的奇怪环境(如android)中工作(有人请验证这一点,有关android的信息可能已过时{{ 3}})