AJAX跨域笔记

跨域GET请求实现:(JSONP方法)
A域: 创建一个SCRIPT标签,地址为B域处理页面(数据于URL上),并增加一个GET参数,该参数为函数名,用于B域
B域:得到请求,返回一个JS结果,该结果是一个函数调用(函数名为A域GET函数名参数),该函数的参数为B域处理后的数据
    因为在SCRIPT标签上,所以该JS加载完成后会直接运行,所以B域设置好的函数调用会直接运行
    但该函数还是不存在的,所以在A域请求时(即创建SCRIPT来请求时候),
    需要设置好B域请求完成后调用的该函数的定义,并置于WINDOW或其他的全局变量上,
    设置的该函数的定义即为成功返回后的调用,所以A域可得到B域请求后的处理结果
跨子域的POST请求实现:(window.domain修改方法)
A子域:创建一个FORM POST请求(把请求数据带上),请求 B子域接受页面 目标为(IFRAME)
B子域:接受到请求,并处理,处理完成之后返回(一个页面,因为在IFRAME里面,所以里面包含的JS会直接运行,
    在返回的该页面中,需要设置window.domain=A子域(页面上直接编码),
    这样,B子域下的该页面世界DOMAIN环境已经变成了A子域,在该页面中需要一个函数调用,
    参数为B子域处理请求后的结果,但该函数未定义,所以需要在A子域请求时(创建FORM POST请求时)创建好该函数,
    并置于WINDOW或其他的全局变量上,该函数得到运行,因为A请求时创建的函数,所以A子域可得到请求结果.)
跨域POST请求实现:(代理页面方法)
A域:创建一个FORM POST请求(把请求数据带上),请求 B域接受页面 目标为(IFRAME)
B域:接到数据,处理,返回(一个页面.因为在IFRAME里面,所以里面包含的JS会直接运行,
    在该页面里在包含一个IFRAME,地址为a域代理页面)
    请求到A域代理,并将处理后的信息标志域URL的HASH值上
A域:代理页面得到运行,取URL的HASH值,解析并回调一个WINDOW上的函数,
    该函数由A域请求时候设置好,并置于WINDOW或其他的全局变量上,
A域:下得到POST请求的结果

安全,该实现是否会被CSRF攻击,XSS攻击
如果被注入了脚本,如何都会被XSS攻击,但是否会被CSRF攻击利用?
因为只要支持HTML标签的网站,都好做好对应的防范,
JSONP方法会被CSRF利用,因为该请求基于GET的上.其他的GET请求也会
POST请求,当无参数时会被CSRF利用.其他情况不会被利用

//OLD---------------------------------------------------------------------------

AJAX跨域

1.可能需要的情况:

    1.GET 

    2.POST

2.实现:

    1.对于GET的请求,最理想的就是JSONP了,可以跨顶级域.实现有JQ的getJSONP

    2.对于POST的请求,跨顶级域目前我未发现非常好的解决办法,所以以下给出的是跨子域的解决方法

          1.在主页面用JS创建一个表单及插入一个IFRMAE,把表单的动作(action)指向IFRAME

          2.设置主页面的document.domain='你的域名'

          3.建立一个代理页面,里面的内容如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript">
    document.domain
='你的域名';
</script>
</head>
<!--BODY段放置需要返回到前端的数据-->
<body>
    {"status":"asdf","get":[],"POST":[],"FILE":[]} 
</body>
</html>

          4.提交数据的方法:直接用JS提交JS创建的表单,之后通过JS获取到IFRAM里的内容(必须要保持主页面跟代理页面相同,否则出现无权访问!)

以下是基于JQ的一个跨域POST插件

View Code
$.extend({
    createUploadIframe: function(id, uri){
        //create frame
        var frameId = 'jUploadFrame' + id;
        var iframeHtml = '<iframe id="' + frameId + '" name="' + frameId + '" style="position:absolute; top:-9999px; left:-9999px"';
        if (window.ActiveXObject) {
            if (typeof uri == 'boolean') {
                iframeHtml += ' src="' + 'javascript:false' + '"';
                
            } else if (typeof uri == 'string') {
                iframeHtml += ' src="' + uri + '"';
                
            }
        }
        iframeHtml += ' />';
        $(iframeHtml).appendTo(document.body);
        return $('#' + frameId).get(0);
    },
    createUploadForm: function(id, data){
        //create form    
        var formId = 'jUploadForm' + id;
        var form = $('<form  action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>');
        if (data) {
            for (var i in data) {
                if(typeof(data[i])=="object"){
                    for(var j in data[i]){
                        $('<input type="hidden" name="' + i + '" value="' + data[i][j] + '" />').appendTo(form);
                    }
                }else{
                    $('<input type="hidden" name="' + i + '" value="' + data[i] + '" />').appendTo(form);
                }
            }
        }
        //set attributes
        $(form).css('position', 'absolute');
        $(form).css('top', '-1200px');
        $(form).css('left', '-1200px');
        $(form).appendTo('body');
        return form;
    },
    
    ajaxPost: function(s){
        // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout        
        s = $.extend({}, $.ajaxSettings, s);
        var id = new Date().getTime()
        var form = $.createUploadForm(id, (typeof(s.data) == 'undefined' ? false : s.data));
        var io = $.createUploadIframe(id, s.secureuri);
        var frameId = 'jUploadFrame' + id;
        var formId = 'jUploadForm' + id;
        // Watch for a new set of requests
        if (s.global && !$.active++) {
            $.event.trigger("ajaxStart");
        }
        var requestDone = false;
        // Create the request object
        var xml = {}
        if (s.global) 
            $.event.trigger("ajaxSend", [xml, s]);
        // Wait for a response to come back
        var uploadCallback = function(isTimeout){
            var io = document.getElementById(frameId);
            try {
                if (io.contentWindow) {
                    xml.responseText = io.contentWindow.document.body ? io.contentWindow.document.body.innerHTML : null;
                    xml.responseXML = io.contentWindow.document.XMLDocument ? io.contentWindow.document.XMLDocument : io.contentWindow.document;
                    
                } else if (io.contentDocument) {
                    xml.responseText = io.contentDocument.document.body ? io.contentDocument.document.body.innerHTML : null;
                    xml.responseXML = io.contentDocument.document.XMLDocument ? io.contentDocument.document.XMLDocument : io.contentDocument.document;
                }
            } 
            catch (e) {
                $.handleError(s, xml, null, e);
            }
            
            if (xml || isTimeout == "timeout") {
                requestDone = true;
                var status;
                try {
                    status = isTimeout != "timeout" ? "success" : "error";
                    // Make sure that the request was successful or notmodified
                    if (status != "error") {
                        // process the data (runs the xml through httpData regardless of callback)
                        var data = $.uploadHttpData(xml, s.dataType);
                        // If a local callback was specified, fire it and pass it the data
                        if (s.success) 
                            s.success(data, status);
                        
                        // Fire the global callback
                        if (s.global) 
                            $.event.trigger("ajaxSuccess", [xml, s]);
                    } else {
                        $.handleError(s, xml, status);
                    }
                } 
                catch (e) {
                    status = "error";
                    $.handleError(s, xml, status, e);
                }
                
                // The request was completed
                if (s.global) 
                    $.event.trigger("ajaxComplete", [xml, s]);
                
                // Handle the global AJAX counter
                if (s.global && !--$.active) 
                    $.event.trigger("ajaxStop");
                
                // Process result
                if (s.complete) 
                    s.complete(xml, status);
                
                $(io).unbind()
                
                setTimeout(function(){
                    try {
                        $(io).remove();
                        $(form).remove();
                    } 
                    catch (e) {
                        $.handleError(s, xml, null, e);
                    }
                    
                }, 100)
                
                xml = null;
            }
        }
        // Timeout checker
        if (s.timeout > 0) {
            setTimeout(function(){
                // Check to see if the request is still happening
                if (!requestDone) 
                    uploadCallback("timeout");
            }, s.timeout);
        }
        try {
        
            var form = $('#' + formId);
            $(form).attr('action', s.url);
            $(form).attr('method', 'POST');
            $(form).attr('target', frameId);
            if (form.encoding) {
                $(form).attr('encoding', 'multipart/form-data');
            } else {
                $(form).attr('enctype', 'multipart/form-data');
            }
            $(form).submit();
            
        } 
        catch (e) {
            $.handleError(s, xml, null, e);
        }
        
        $('#' + frameId).load(uploadCallback);
        return {
            abort: function(){
                //function
            }
        };
    },
    
    uploadHttpData: function(r, type){
        var data = !type;
        data = type == "xml" || data ? r.responseXML : r.responseText;
        // If the type is "script", eval it in global context
        if (type == "script") 
            $.globalEval(data);
        // Get the JavaScript object, if JSON is used.
        if (type == "json") 
            eval("data = " + data);
        // evaluate scripts within html
        if (type == "html") 
            $("<div>").html(data).evalScripts();
        
        return data;
    }
})

此文件需要代理配合,代理文件如上,调用此插件前调需用document.domain='你的域名';

此插件是ajaxFileUpload插件的修改版.

原文地址:https://www.cnblogs.com/liushannet/p/2349441.html