2012-02-22 45 views
21

在实际尝试使用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可以使用。

+0

如果你做了一个跨域请求,它将会失败,'readystate = 4'和'statuscode = 0',这与中止请求类似。 既然你需要防范中止请求,为什么你需要这个检查?我觉得这个安全措施是从外部强制执行的,你无法控制它,所以从环境中的任何检查在定义上都是错误的。所以我认为你不应该检查它,只是让请求失败。 – Halcyon 2012-03-03 20:38:12

回答

8

有趣的问题!我四处搜寻,找不到任何其他东西,但是当我乱搞一些测试代码时,我遇到了这个问题。如果你只是想要一个简单的方式来测试一个URL而不提出请求,我会按照你的方式来做。如果你不关心的是判断一个请求,你可以试试这个:

做一个简单的Ajax请求,任何你想要的网址:

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

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

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

现在,唯一的问题是,isRejected()将评估为true为每一个情况下无法载入网页(即404未找到,等),但你可以检查状态代码:

ajaxRequest.status; 

它看起来像上面的一行将返回0当你试图打破同源策略,但它会返回在其他情况下,适当的错误代码(再次,即404)。

所以包裹起来,也许你可以尝试做这样的事情:

function testSameOrigin(testUrl) { 

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

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

没有一个明确的答案,以任何方式,但我希望它可以帮助你找出你在找什么!

+0

是的,这是一个有趣的方法。在我最初的情况下,我想通过尝试“验证”URL来摆脱在执行拒绝的ajax调用时遇到的令人讨厌的控制台错误。我还刚刚发现,在本地文件(文件:协议)上执行ajax请求也每次都失败。所以这是另一种情况下检查... – David 2012-02-29 23:37:24

+0

您可以通过将'isLocal'标志设置为'true' http://api.jquery.com/jQuery来为本地文件使用ajax。阿贾克斯/ jQuery的#阿贾克斯的设置 – Steve 2012-03-01 03:11:28

0

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

+0

我不确定为什么所有的答案都是关于如何制作或不制作跨浏览器ajax请求,这根本就不是我所要求的...我需要更清楚吗? – David 2012-02-29 00:17:24

10

在实际尝试使用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 http://example.com‘其中实际上它应该返回true”你testSameOrigin功能将为返回false’。

如果您在修改document.domain计划,您可以添加只需在脚本中添加该支票。

如果您打算使用CORS(请参阅上面的链接)来允许跨域通信,它也会返回一个错误的否定信息,但是如果您使用的是CORS,则会列出可与之通信的域名列表,而您可以将该列表添加到该功能中。

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

或许不会,但它可能是值得一提的是你在控制台从史蒂夫的回答看可能是“观测者的困境” ......这些错误看起来像他们从控制台试图检查所产生的其他窗口,不一定来自脚本。

假设你不打算使用document.domain或使用CORS,你的原始解决方案可能会更好,因为它不需要额外的请求来确定服务器是否可用。即使你正在做一些跨域脚本,修改你现在可以适应的功能也许是你最好的选择。

+1

,而这是检查CORS的好办法要求它打破了在IE7而产生的锚不会返回任何信息有关的链接,例如在IE7它评估等环节''将返回'a.href =>“main.html”'''a.hostname =>“”'等我仍然试图找出如何处理这在IE7 tho。但找不到任何好的解决方案。因为它永远不会创建完整的href。 – zanona 2012-08-29 15:07:45

+0

你会添加什么document.domain检查?简单地用'document.domain'替换'loc.hostname'是否正确? – 2014-07-07 20:03:39

+0

@BT'a.hostname'仍然是“foo.example.com”,“document.domain”只是“example.com”。它必须是一个特殊情况检查,即如果你知道你正在将'document.domain'重写为“example.com”,则主机名检查将类似于'a.hostname == loc.hostname || a.hostname ==“foo.example.com”' – 2014-07-07 21:04:58

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:' 
} 

告诫我能想到的:

1

尝试这种解决方案也是如此。

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