检查是否可以使用 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";
您可以添加一个带有 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 确实抛出。
我想检查服务器是否 可访问 并具有 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";
您可以添加一个带有 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 确实抛出。