1

我想进行一个不需要响应的跨域 AJAX 调用(它只是用于收集数据)。我知道您插入脚本标签的 JSONP,但由于我不会返回任何 JSONP,所以我想也许有更好的方法。是否有或者我仍然需要使用相同的方法?

4

4 回答 4

3

如果您控制目标域(收集数据的域)

您可能希望允许“外国”来源,因此您可以使用普通的 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 注入站点并做令人讨厌的坏坏事。讨厌。

于 2012-11-13T15:17:31.277 回答
0

您可以动态创建表单并将其值发布到使用表单的目标属性的隐藏 iframe。

于 2012-11-13T15:00:13.217 回答
0

您可以使用隐藏的 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 等)

于 2012-11-13T15:01:05.867 回答
0

我知道的唯一选择是让服务器为您执行查询(如果这是一个选项)。换句话说,在将执行请求的 Web 服务器上提供某种服务......特别是因为您不需要解析任何返回数据,这将是相当微不足道的。例如,您可以file()在 PHP 中使用一个简单的调用:

http://us3.php.net/manual/en/function.file.php

于 2012-11-13T15:03:08.997 回答