简体   繁体   中英

Cross-domain AJAX where no response is needed?

I want to make a cross-domain AJAX call which requires no response (it's simply for collecting data). I know about JSONP where you insert a script tag but since I will not return any JSONP I'm thinking maybe there's a better way. Is there or do I still need to use the same method?

If you're in control of the target domain (the one which collects data)

You might want to allow "foreign" origins, so you can access it with normal XMLHttpRequests.

In Apache .htaccess that would be something like (requires mod_headers):

Header set Access-Control-Allow-Origin *

Or in PHP:

header('Access-Control-Allow-Origin: *');

Actually in IE8+, crossdomain XmlHttpRequests use a special proprietary interface (XDomainRequest), that jQuery (the last time I checked) does not normalize. So, you'd need to implement a custom Ajax transport to make jQuery work with XSS Ajax. That would be something like:

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();
                    }
                }
            };
        }
    });
}

(I actually use this in production, it should work)


If you're NOT in control of the target domain

Anything that requests a resource (be it an image, a page or script) will do it.

A script probably is still the "lightest" option since it isn't rendered (and hence does not require any styling for it to be hidden and does not cause any reflow in any case).

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);

Limitations: If you're not in control over what is returned by the call, and the call returns invalid javascript, and you execute this code before other code on the page, the javascript interpreter of some browsers might be interrupted (depending on the severity of the error caused by this invalid code).

Also note that if you're not in control of the target domain, and the target domain is not trustworthy, they might actually inject nasty bad javascript into the site and do nasty bad bad things. Nasty.

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

You could use a hidden iframe, inwhich you would create a hidden form that targets it:

// 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!" });



A few notes:
I can't remember if the iframe has to be appended to the document.
I can't remember if you can target the iframe as I did(no id or the such)

The only alternative I'd be aware of is having the server do the query for you if that's an option. In other words, provide a service of some sort on the web server that will do the request... In particular since you don't need to parse any return data, this would be fairly trivial. For example, you can use a simple file() call in PHP:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM