跨域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利用.其他情况不会被利用
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>
<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;
}
})
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插件的修改版.