javascript 检查是否适用同源政策

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9404793/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 06:33:39  来源:igfitidea点击:

Check if same origin policy applies

javascriptjqueryajaxcross-domaincross-domain-policy

提问by David Hellsing

Is there a "safe" way to check if the same origin policy applies to an URL before actually trying to use ajax methods? Here is what I have:

在实际尝试使用 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;
}

This sort of works, but it's kind of a manual guess based on the wikipedia article. Is there a better way of pre-checking cross domain allowance? jQuery is OK to use.

这种工作,但它是一种基于维基百科文章的手动猜测。有没有更好的方法来预检查跨域限额?jQuery 可以使用。

采纳答案by Steve

Interesting question! I searched around and couldn't find anything other than what you posted, but I did come across this when I was messing around with some test code. If you just want a simple way to test a URL without making a request, I'd do it the way you're doing it. If you don't care about making a request to test, you could try this:

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

Make a simple ajax request to whatever URL you want:

向您想要的任何 URL 发出一个简单的 ajax 请求:

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

which returns a jqXHRobject, which you can then check:

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

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

Now, the only problem with this is that isRejected()will evaluate to truefor every single case where the page doesn't load (i.e. 404 Not Found, etc.), but you can check the status code with:

现在,唯一的问题是对于页面未加载的每种情况(即 404 Not Found 等)isRejected()都会评估true为,但您可以使用以下方法检查状态代码:

ajaxRequest.status;

It looks like the above line will return 0when you attempt to break the same origin policy, but it will return the appropriate error code (again, i.e. 404) in other cases.

0当您尝试破坏同源策略时,看起来上面的行会返回,但在其他情况下它会返回适当的错误代码(再次,即 404)。

So to wrap up, maybe you could try doing something like:

所以总结一下,也许您可​​以尝试执行以下操作:

function testSameOrigin(testUrl) {

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

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

Not a definitive answer by any means, but I hope it helps you figure out what you're looking for!

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

回答by Dagg Nabbit

Is there a "safe" way to check if the same origin policy applies to an URL before actually trying to use ajax methods? Here is what I have:

在实际尝试使用 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;
}

This is a safe and reliable way of doing it, provided you are doing (or rather not doing) certain things.

这是一种安全可靠的方法,前提是您正在做(或不做)某些事情。

This sort of works, but it's kind of a manual guess based on the wikipedia article.

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

This should fully work under the "normal" circumstances. It will need to be modified if you are planning to use cross-domain scripting.

这应该在“正常”情况下完全起作用。如果您计划使用跨域脚本,则需要对其进行修改。

If you modify document.domainin your scripts, for example from "foo.example.com" and "bar.example.com" to "example.com" your testSameOriginfunction would return falsefor "http://example.com", where in fact it should return true.

如果您修改document.domain脚本,例如从“foo.example.com”和“bar.example.com”到“example.com”,您的testSameOrigin函数将返回falsehttp://example.com”,实际上它应该返回true

If you are planning on modifying document.domain, you can add simply add a check for that in your script.

如果您打算修改document.domain,您只需在脚本中添加一个检查即可。

If you are planning on using CORS (see the link above) to allow cross-domain communication, it will also return a false negative. But if you are using CORS, you will have a list of domains that you can communicate with, and you can add that list to this function as well.

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

Is there a better way of pre-checking cross domain allowance? jQuery is OK to use.

有没有更好的方法来预检查跨域限额?jQuery 可以使用。

Probably not, although it may be worth mentioning that what you are seeing in the console from Steve's answer might be the "observer's dilemma" ... Those errors look like they are resulting from the console trying to inspect the other window, not necessarily from the script.

可能不是,尽管值得一提的是,您在 Steve 的回答中在控制台中看到的可能是“观察者的困境”……这些错误看起来像是由控制台尝试检查另一个窗口引起的,不一定来自剧本。

Assuming you're not messing with document.domainor using CORS, your original solution is probably better, as it doesn't need to make an extra request to determine whether the server is available or not. Even if you are doing some cross-domain scripting, modifying the function you have now to accommodate it is probably your best bet.

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

回答by jo_asakura

Try this solution as well.

也试试这个解决方案。

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

回答by B T

Building off of Dagg Nabbit's answer, this seems a little more complete:

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

Caveats I can think of:

我能想到的注意事项:

回答by Alberto De Caro

Another way to execute cross domain script is using JSON-P. You can also read this article. Otherwise, the cross domain scripting is not allowed by the same origin policy.

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