检查是否可以使用 JavaScript 访问在线资源,不需要同源策略来允许它

Check if online resource is reachable with JavaScript, not requiring the The Same Origin Policy to allow it

我想检查服务器是否 可访问 并具有 JavaScript 功能。

通过可达,我的意思是,如果服务器响应,我不关心哪个 HTTP 状态代码,它是可达的。

Whosebug/Google 帮我实现了这个功能:

function check(target)
{
    var xhr = new XMLHttpRequest();
    var target = "https://"+target+"/index.php";
    var num = Math.round(Math.random() * 10000);

    xhr.open("HEAD", target + "?num=" + num, true);
    xhr.send();
    xhr.addEventListener("readystatechange", processRequest, false);

    function processRequest(e)
    {
      if (xhr.readyState == 4)
      {
        if (xhr.status !== 0)
        {
          return true;
        }
        else
        {
          return false;
        }
      }
    }
}

如果目标允许使用 Access-Control-Allow-Origin: *(或特定于客户端)的操作,则效果很好。但事实并非如此。

我遇到过很多解决方案,它们似乎都依赖于此。

如何使用 JavaScript 检查服务器是否可访问,独立于服务器上的 Access-Control-Allow-Origin 设置?

编辑: 我只是想补充一点,我无法修改目标(例如更改 headers),但我能够识别资源应该可用(例如 https://target/this-specific-site.php

edit2: 我正在尝试按照@Vic 的建议实施一个解决方案; try it here:

function chk(){

var img = new Image();   // Create new image element

img.onload = function(){
    return false;
};

img.onerror = function() {
    return true;
};

// Try to change this URL to nonexistant image
img.src = 'https://www.google.com/images/srpr/logo3w.png'; // Set source path

}

if (chk())
{
alert("IMAGE LOADED");
}
else
{
alert("IMAGE FAILED TO LOAD ("+chk()+")");
}

但是函数出现returnundefined,所以检查失败。

edit3: 我需要函数给我一个 return 值。

这是不可能的。它将允许同源策略旨在保护的信息泄漏。

例如用户工作的公司是否有包含特定 URL 的内联网页面?

这可能会导致诸如确定公司使用哪个版本的 Microsoft Sharepoint(举一个众所周知的例子)、它安装在什么 URL 上,然后使用该信息进行社会工程等事情攻击。

这就够了吗?您不能有异步函数 (onerror/onload) return 值。相反,您可以执行类似于回调的操作。

function conditional(status){
  if(status)
  {
    console.log("Hey, the image loaded correctly.");
  }
  else
  {
    console.log("Bruh, the server is dead.");
  }
}

var tester = new Image();
tester.onload = function() {
  conditional(true);
};
tester.onerror = function() {
  conditional(false);
};
tester.src="https://i.imguhr.com/Ru1q3sS.jpg";

https://jsbin.com/veruzegohe/1/edit?html,console,output

您可以添加一个带有 src 属性的脚本标记,引用您知道服务器上存在的文件,然后使用 onerror 事件检测是否找不到该文件:

<script src="nonexistent.js" onerror="alert('error!')"></script>

归功于此 answer 的最后一条评论。

您不应该 运行 使用此解决方案解决跨源问题。

更新

如果您不想冒险和 运行 脚本,您可以改用 img 标签。使用 onerror 事件检测失败,使用 onload 事件检测成功:

<html>
    <head>
        <img src="https://www.google.com/images/srpr/logo3w.pngx" onerror="failure()" onload="success()" height="0" width="0">
        <script>
            let _isSuccess = false;
            function success() {
                _isSuccess = true;
            }

            function failure() {
                _isSuccess = false;
            }

            function isSuccess() {
                console.log(`is success == ${_isSuccess}`);
                return _isSuccess;
            }

        </script>
    </head>
    <body onload="isSuccess()">
        <h1>Hello World!</h1>
    </body>
</html>

在现代浏览器中,您可以使用 fetch API 及其 no-cors 请求模式,这将 return 一个 opaque 响应(您将无法执行其他任何内容):

fetch('http://google.com', {mode: 'no-cors'}).then(r=>{
  console.log('google is reachable');
  })
  .catch(e=>{
    console.log('google is not there');
    });
fetch('http://fakeservertahtdoesntexist.com', {mode: 'no-cors'}).then(r=>{
  console.log('fake is reachable');
  })
  .catch(e=>{
    console.log('fake is not there');
    });

奇怪的是,我的 FF 没有抛出(但它也没有),而我的 chrome 确实抛出。