Ido*_*ham 553 javascript ajax cross-domain
如何通过JavaScript发送跨域POST请求?
注意 - 它不应该刷新页面,然后我需要抓取并解析响应.
ryn*_*nop 381
更新:在继续之前,每个人都应该阅读并理解CORS上的html5rocks教程.这很容易理解,也很清楚.
如果您控制正在POST的服务器,只需通过在服务器上设置响应标头来利用"跨源资源共享标准".这个答案将在本主题的其他答案中讨论,但在我看来并不是很清楚.
简而言之,您将如何完成从from.com/1.html到to.com/postHere.php的跨域POST(以PHP为例).注意:您只需要Access-Control-Allow-Origin
为非OPTIONS
请求设置- 此示例始终为较小的代码段设置所有标头.
在postHere.php中设置以下内容:
switch ($_SERVER['HTTP_ORIGIN']) {
case 'http://from.com': case 'https://from.com':
header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']);
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
header('Access-Control-Max-Age: 1000');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
break;
}
Run Code Online (Sandbox Code Playgroud)
这允许您的脚本进行跨域POST,GET和OPTIONS.当你继续阅读时,这将变得清晰......
从JS设置跨域POST(jQuery示例):
$.ajax({
type: 'POST',
url: 'https://to.com/postHere.php',
crossDomain: true,
data: '{"some":"json"}',
dataType: 'json',
success: function(responseData, textStatus, jqXHR) {
var value = responseData.someKey;
},
error: function (responseData, textStatus, errorThrown) {
alert('POST failed.');
}
});
Run Code Online (Sandbox Code Playgroud)在步骤2中执行POST时,浏览器将向服务器发送"OPTIONS"方法.这是浏览器的"嗅探",看看服务器是否很酷,你发布它.如果请求来自" http://from.com "或" https://from.com " ,则服务器以"Access-Control-Allow-Origin"响应,告知浏览器可以POST | GET | ORIGIN .由于服务器没问题,浏览器会发出第二个请求(这次是POST).让您的客户端设置它正在发送的内容类型是一种很好的做法 - 所以您也需要允许它.
MDN对HTTP访问控制进行了很好的描述,详细介绍了整个流程的工作原理.根据他们的文档,它应该"在支持跨站点XMLHttpRequest的浏览器中工作".然而,这有点误导,因为我认为现代浏览器只允许跨域POST.我只用safari,chrome,FF 3.6验证了这个功能.
如果您这样做,请记住以下内容:
Dan*_*ich 121
如果您控制远程服务器,您应该使用CORS,如本答案中所述 ; IE8及更高版本支持它,以及所有最新版本的FF,GC和Safari.(但在IE8和9中,CORS不允许您在请求中发送cookie.)
因此,如果您不控制远程服务器,或者您必须支持IE7,或者您需要cookie并且您必须支持IE8/9,那么您可能希望使用iframe技术.
这是示例代码; 我在IE6,IE7,IE8,IE9,FF4,GC11,S5上进行了测试.
function crossDomainPost() {
// Add the iframe with a unique name
var iframe = document.createElement("iframe");
var uniqueString = "CHANGE_THIS_TO_SOME_UNIQUE_STRING";
document.body.appendChild(iframe);
iframe.style.display = "none";
iframe.contentWindow.name = uniqueString;
// construct a form with hidden inputs, targeting the iframe
var form = document.createElement("form");
form.target = uniqueString;
form.action = "http://INSERT_YOUR_URL_HERE";
form.method = "POST";
// repeat for each parameter
var input = document.createElement("input");
input.type = "hidden";
input.name = "INSERT_YOUR_PARAMETER_NAME_HERE";
input.value = "INSERT_YOUR_PARAMETER_VALUE_HERE";
form.appendChild(input);
document.body.appendChild(form);
form.submit();
}
Run Code Online (Sandbox Code Playgroud)
谨防!您将无法直接读取POST的响应,因为iframe存在于单独的域中.帧不允许来自不同域的相互通信; 这是同源政策.
如果您控制远程服务器但不能使用CORS(例如,因为您使用的是IE8/IE9,并且需要使用cookie),则有办法解决同源策略,例如使用window.postMessage
和/或许多库中的一个允许您在旧版浏览器中发送跨域跨框架消息:
如果您不控制远程服务器,则无法读取POST的响应时间段.否则会引起安全问题.
Lou*_*nco 47
伪代码
var ifr = document.createElement('iframe');
var frm = document.createElement('form');
frm.setAttribute("action", "yoururl");
frm.setAttribute("method", "post");
// create hidden inputs, add them
// not shown, but similar (create, setAttribute, appendChild)
ifr.appendChild(frm);
document.body.appendChild(ifr);
frm.submit();
Run Code Online (Sandbox Code Playgroud)
你可能想要设置iframe的样式,隐藏和绝对定位.不确定浏览器是否允许跨站点发布,但如果是这样,这是如何做到的.
Ala*_*ier 23
把事情简单化:
跨域POST:
使用crossDomain: true,
不应该刷新页面:
不,它不会刷新页面,因为当服务器发回响应时将调用success
或error
异步回调.
$.ajax({
type: "POST",
url: "http://www.yoururl.com/",
crossDomain: true,
data: 'param1=value1¶m2=value2',
success: function (data) {
// do something with server response data
},
error: function (err) {
// handle your error logic here
}
});
Run Code Online (Sandbox Code Playgroud)
小智 16
如果您可以访问所涉及的所有服务器,请将以下内容放在其他域中请求的页面的回复标题中:
PHP:
header('Access-Control-Allow-Origin: *');
Run Code Online (Sandbox Code Playgroud)
例如,在Drupal的xmlrpc.php代码中,您可以这样做:
function xmlrpc_server_output($xml) {
$xml = '<?xml version="1.0"?>'."\n". $xml;
header('Connection: close');
header('Content-Length: '. strlen($xml));
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/x-www-form-urlencoded');
header('Date: '. date('r'));
// $xml = str_replace("\n", " ", $xml);
echo $xml;
exit;
}
Run Code Online (Sandbox Code Playgroud)
这可能会产生安全问题,您应该确保采取适当的措施来验证请求.
小智 6
创建两个隐藏的iframe(将"display:none;"添加到css样式).将您的第二个iframe指向您自己域中的内容.
创建一个隐藏的表单,将其方法设置为使用target =你的第一个iframe"发布",并可选择将enctype设置为"multipart/form-data"(我想你想要发送POST,因为你想发送多部分数据,比如图片?)
准备好后,将表单提交()POST.
如果您可以让其他域返回将使用Iframe进行跨域通信的JavaScript(http://softwareas.com/cross-domain-communication-with-iframes),那么您很幸运,并且您可以捕获响应同样.
当然,如果您想将服务器用作代理,则可以避免所有这些.只需将表单提交给您自己的服务器,服务器将请求代理到其他服务器(假设其他服务器未设置为通知IP差异),获取响应并返回您喜欢的任何内容.
还有一点需要注意!在上面的例子中,它描述了如何使用
$.ajax({
type : 'POST',
dataType : 'json',
url : 'another-remote-server',
...
});
Run Code Online (Sandbox Code Playgroud)
JQuery 1.6及更低版本存在跨域XHR的错误.据Firebug称,除了OPTIONS之外没有任何请求被发送.没有POST.完全没有.
花了5个小时测试/调整我的代码.在远程服务器(脚本)上添加大量标头.没有任何影响.但后来,我将JQuery lib更新为1.6.4,一切都像魅力一样.
如果您想在使用JQuery AJAX的ASP.net MVC环境中执行此操作,请执行以下步骤:(这是此线程提供的解决方案的摘要)
假设"caller.com"(可以是任何网站)需要发布到"server.com"(ASP.net MVC应用程序)
在"server.com"应用程序的Web.config上添加以下部分:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS" />
</customHeaders>
</httpProtocol>
Run Code Online (Sandbox Code Playgroud)在"server.com"上,我们将在我们将要发布的控制器(称为"Home")上执行以下操作:
[HttpPost]
public JsonResult Save()
{
//Handle the post data...
return Json(
new
{
IsSuccess = true
});
}
Run Code Online (Sandbox Code Playgroud)然后从"caller.com",将表格(使用html id"formId")发布到"server.com",如下所示:
$.ajax({
type: "POST",
url: "http://www.server.com/home/save",
dataType: 'json',
crossDomain: true,
data: $(formId).serialize(),
success: function (jsonResult) {
//do what ever with the reply
},
error: function (jqXHR, textStatus) {
//handle error
}
});
Run Code Online (Sandbox Code Playgroud)