【问题标题】:Check if online resource is reachable with JavaScript, not requiring the The Same Origin Policy to allow it检查是否可以使用 JavaScript 访问在线资源,而不需要同源策略来允许它
【发布时间】:2017-08-03 04:08:08
【问题描述】:

我想通过 JavaScript 函数检查服务器是否可访问

可达,我的意思是,如果服务器应答,我不在乎哪个 HTTP 状态码,它是可达的。

Stackoverflow/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 设置?

编辑: 我只是想补充一点,我不能修改目标(例如更改标题),但我能够识别应该可用的资源(例如 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()+")");
}

但该函数似乎返回undefined,因此检查失败。

edit3:我需要这个函数给我一个返回值。

【问题讨论】:

  • (1) 从网站获取图片 (2) 将其加载到您的网站 (3) 如果出现错误,则假设网站已关闭。
  • @Quentin,这些页面确实会导致 0,如果您尝试使用 https://enable-cors.org/ 作为目标的脚本,我想您会明白我的意思
  • @Vic,我正在尝试在另一个 Stackoverflow 帖子的帮助下实现这一点。但对我来说,如果它失败了,如果它加载了,函数都会被执行。见:jsbin.com/worutemobe/edit?html,console,output
  • 刚刚检查了你的代码...不是那样工作的,哈哈

标签: javascript http access-control


【解决方案1】:

在现代浏览器中,您可以使用fetch API 及其no-cors 请求模式,这将返回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 会抛出。

【讨论】:

  • 这看起来很有希望!我已经尝试实现它,我得到了undefined 的回复。见jsbin.com/hadoluqire/edit?html,console,output
  • 所以现在你必须了解asynchronous scripting(无论如何你将使用的任何hack都是异步的)。
  • 嗯。这变得比我想象的要复杂。不过谢谢!
  • 注意 fetch() 是一个实验性功能:“请注意,实验性技术的语法和行为可能会发生变化”(来源:developer.mozilla.org/en-US/docs/Web/API/…
  • @Perspectivus fetch 在生活标准中,我认为它不会很快发生巨大变化。有些方法还没有被 UA 实现,但是很多 API 也是如此(ehich eill 也有这个默认的 MDN 通知)
【解决方案2】:

您可以添加一个带有 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>

【讨论】:

  • 会不会和加载外部图片一样?加载脚本非常可怕。
  • 这似乎是一个非常相似的选项,但我不知道如何在函数中使用它来给我falsetrue
  • @SaAtomic,为了避免异步问题,在 标签的 onLoad() 事件中调用 isSuccess() 函数
【解决方案3】:

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

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

【讨论】:

  • 这很整洁。似乎对我来说工作得很好。感谢您帮助一个 JS 菜鸟。
  • 阅读回调,兄弟。它会改变你的 JS 生活。顺便说一句,检查我是否回答了你的问题。 (我可以这么说吗?对不起,太菜鸟了)
  • 我还是有点迷茫,尝试在我的脚本中实现它。我不明白如何将它用作返回 true 或 false 的函数,所以我可以在另一个函数中执行 if(check()){[...];}
  • Bruh,你不能异步返回。 IF 语句需要同步函数。我建议将您的脚本放在条件函数中。
  • 这是一个很棒的小技巧,可以确定 Web 服务器是否已启动/可访问。
【解决方案4】:

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

例如用户所在的公司是否有带有特定 URL 的 Intranet 页面?

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

【讨论】:

  • 这必须是可以实现的,正如@Vic 建议的那样,我可以尝试从服务器检索图像并查看它是否加载。
  • @SaAtomic 你也可以通过代理运行。让 PHP 执行 GET 请求。
  • 实际上他们确实发明了opaque 响应和no-cors 请求模式,通过只允许请求为HEAD、GET 或POST 应该足够安全。如果我理解正确,它会避免 HEAD + GET 或 HEAD + POST 但我不确定我是否正确,我也不确定它如何避免端口嗅探。
猜你喜欢
  • 2020-06-01
  • 2019-12-18
  • 2017-05-03
  • 2016-01-10
  • 2020-01-26
  • 2011-08-24
  • 2021-10-21
  • 2020-06-06
  • 1970-01-01
相关资源
最近更新 更多