我想进行一个不需要响应的跨域 AJAX 调用(它只是用于收集数据)。我知道您插入脚本标签的 JSONP,但由于我不会返回任何 JSONP,所以我想也许有更好的方法。是否有或者我仍然需要使用相同的方法?
4 回答
如果您控制目标域(收集数据的域)
您可能希望允许“外国”来源,因此您可以使用普通的 XMLHttpRequests 访问它。
在 Apache .htaccess 中,这将类似于(需要 mod_headers):
Header set Access-Control-Allow-Origin *
或者在 PHP 中:
header('Access-Control-Allow-Origin: *');
实际上在 IE8+ 中,跨域 XmlHttpRequests 使用一个特殊的专有接口(XDomainRequest),jQuery(我上次检查的时候)没有规范化。因此,您需要实现自定义Ajax 传输以使 jQuery 与 XSS Ajax 一起工作。那将是这样的:
if (window.XDomainRequest) {
$.ajaxTransport(function (options, originalOptions, jqXHR) {
var xdr;
if (window.location.host != options.url.match(/:\/\/(.[^\/]+)/)[1]) {
return {
send: function (headers, completeCallback) {
xdr = new XDomainRequest();
xdr.onload = function () {
var responses = {
text: xdr.responseText
};
completeCallback(200, 'success', responses);
};
xdr.onerror = xdr.ontimeout = function () {
var responses = {
text: xdr.responseText
};
completeCallback(400, 'failed', responses);
};
xdr.open(options.type, options.url);
xdr.send(options.data);
},
abort: function () {
if (xdr) {
xdr.abort();
}
}
};
}
});
}
(我实际上在生产中使用它,它应该可以工作)
如果您无法控制目标域
任何请求资源的东西(无论是图像、页面还是脚本)都会这样做。
脚本可能仍然是“最轻”的选项,因为它没有被渲染(因此不需要任何样式来隐藏它,并且在任何情况下都不会导致任何重排)。
var req = document.createElement('script');
req.setAttribute('src', '//example.com/api/count?' + encodeURI('id=1&data=foo bar'));
document.body.appendChild(req);
document.body.removeChild(req);
限制:如果您无法控制调用返回的内容,并且调用返回无效的 javascript,并且您在页面上的其他代码之前执行此代码,则某些浏览器的 javascript 解释器可能会被中断(取决于严重程度由这个无效代码引起的错误)。
另请注意,如果您无法控制目标域,并且目标域不值得信赖,他们实际上可能会将令人讨厌的坏 javascript 注入站点并做令人讨厌的坏坏事。讨厌。
您可以动态创建表单并将其值发布到使用表单的目标属性的隐藏 iframe。
您可以使用隐藏的 iframe,在其中创建一个以它为目标的隐藏表单:
// data is a key-value pair'd object as such:{"key":"value, "key":"value" }
window.xss = function (url, method, data) {
// function to make creating hidden form elements easier:
function hEle = function (key,value) {
var ele = document.createElement("input");
ele.type = "hidden";
ele.name = key;
ele.value = value;
return ele;
}
// create the iframe(can't remember if this has to be appended to the DOM):
var myIframe = document.createElement("iframe");
// create the form:
var myForm = document.createElement("form");
myForm.setAttribute("action", url);
myForm.setAttribute("method", method||"GET");
myForm.target = myIframe;
// loop through `data` adding hidden elements to the form:
for (var key in data) {
if(data.hasOwnProperty(key)) {
myForm.appendChild(hEle(key, data[key]));
}
}
// Once everything is setup, submit the form
myForm.submit();
}
// to use:
xss("http://siteIDonthost.com/", "POST", {"myKey" : "OHNOES, VALUE!" });
一些注意事项:
我不记得 iframe 是否必须附加到文档中。
我不记得你是否可以像我一样定位 iframe(没有 id 等)
我知道的唯一选择是让服务器为您执行查询(如果这是一个选项)。换句话说,在将执行请求的 Web 服务器上提供某种服务......特别是因为您不需要解析任何返回数据,这将是相当微不足道的。例如,您可以file()
在 PHP 中使用一个简单的调用: