如何通过JavaScript发送跨域POST请求?
注释-它不应该刷新页面,然后我需要抓取并解析响应。
如何通过JavaScript发送跨域POST请求?
注释-它不应该刷新页面,然后我需要抓取并解析响应。
当前回答
如果您控制远程服务器,您可能应该使用CORS,如回答中所述;它在IE8及以上版本,以及FF、GC和Safari的所有最新版本中都得到支持。(但是在IE8和ie9中,CORS不允许你在请求中发送cookie。)
所以,如果你不控制远程服务器,或者你必须支持IE7,或者你需要cookie并且你必须支持IE8/9,你可能会想要使用iframe技术。
创建一个名称唯一的iframe。(iframes为整个浏览器使用全局名称空间,因此请选择其他网站不会使用的名称。) 构造一个带有隐藏输入的表单,以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();
}
小心!您不能直接读取POST的响应,因为iframe存在于一个单独的域中。帧不允许与来自不同域的帧相互通信;这是同源策略。
如果你控制远程服务器,但你不能使用CORS(例如,因为你在IE8/IE9上,你需要使用cookie),有一些方法可以绕过同源策略,例如使用window。postMessage和/或允许你在旧浏览器中发送跨域跨帧消息的库之一:
汽门 XSSInterface EasyXDM jQuery PostMessage插件
如果不控制远程服务器,就不能读取POST的响应,句号。否则会导致安全问题。
其他回答
CORS是为你准备的。 CORS是“跨域资源共享”,是一种发送跨域请求的方式。现在XMLHttpRequest2和Fetch API都支持CORS,它可以发送POST和GET请求
但它也有局限性。服务器需要指定Access-Control-Allow-Origin,不能设置为“*”。
如果你想要任何origin都可以发送请求给你,你需要JSONP(也需要设置Access-Control-Allow-Origin,但可以是'*')
对于很多请求方式,如果你不知道如何选择,我认为你需要一个完整的功能组件来做到这一点。让我介绍一个简单的组件https://github.com/Joker-Jelly/catta
如果你正在使用现代浏览器(> IE9, Chrome, FF, Edge等),非常建议你使用一个简单但美丽的组件https://github.com/Joker-Jelly/catta.It没有依赖,小于3KB,它支持Fetch, AJAX和JSONP与相同致命的示例语法和选项。
catta('./data/simple.json').then(function (res) {
console.log(res);
});
它还支持所有方式导入到您的项目,如ES6模块,CommonJS,甚至HTML中的<script>。
创建一个iFrame, 在里面放入一个隐藏输入的表单, 将表单的动作设置为URL, 向文档中添加iframe 提交表格
伪代码
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();
你可能想样式iframe,隐藏和绝对定位。不确定跨站点发布将被浏览器允许,但如果是这样,这是如何做到的。
如果您控制远程服务器,您可能应该使用CORS,如回答中所述;它在IE8及以上版本,以及FF、GC和Safari的所有最新版本中都得到支持。(但是在IE8和ie9中,CORS不允许你在请求中发送cookie。)
所以,如果你不控制远程服务器,或者你必须支持IE7,或者你需要cookie并且你必须支持IE8/9,你可能会想要使用iframe技术。
创建一个名称唯一的iframe。(iframes为整个浏览器使用全局名称空间,因此请选择其他网站不会使用的名称。) 构造一个带有隐藏输入的表单,以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();
}
小心!您不能直接读取POST的响应,因为iframe存在于一个单独的域中。帧不允许与来自不同域的帧相互通信;这是同源策略。
如果你控制远程服务器,但你不能使用CORS(例如,因为你在IE8/IE9上,你需要使用cookie),有一些方法可以绕过同源策略,例如使用window。postMessage和/或允许你在旧浏览器中发送跨域跨帧消息的库之一:
汽门 XSSInterface EasyXDM jQuery PostMessage插件
如果不控制远程服务器,就不能读取POST的响应,句号。否则会导致安全问题。
更新:在继续之前,每个人都应该阅读并理解html5rocks关于CORS的教程。它很容易理解,也很清楚。
如果您控制被post的服务器,只需通过在服务器上设置响应头来利用“跨源资源共享标准”。这个答案在本帖的其他答案中讨论过,但在我看来不是很清楚。
简而言之,下面是如何完成从from.com/1.html到to.com/postHere.php的跨域POST(以PHP为例)。注意:你只需要为NON OPTIONS请求设置Access-Control-Allow-Origin -这个例子总是为一个较小的代码片段设置所有的头部。
In postHere.php setup the following: 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; } This allows your script to make cross domain POST, GET and OPTIONS. This will become clear as you continue to read... Setup your cross domain POST from JS (jQuery example): $.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.'); } });
When you do the POST in step 2, your browser will send a "OPTIONS" method to the server. This is a "sniff" by the browser to see if the server is cool with you POSTing to it. The server responds with an "Access-Control-Allow-Origin" telling the browser its OK to POST|GET|ORIGIN if request originated from "http://from.com" or "https://from.com". Since the server is OK with it, the browser will make a 2nd request (this time a POST). It is good practice to have your client set the content type it is sending - so you'll need to allow that as well.
MDN有一篇关于HTTP访问控制的文章,详细介绍了整个流程是如何工作的。根据他们的文档,它应该“在支持跨站XMLHttpRequest的浏览器中工作”。这有点误导,然而,因为我认为只有现代浏览器允许跨域POST。我只验证了这适用于safari,chrome,FF 3.6。
如果你这样做,请记住以下几点:
Your server will have to handle 2 requests per operation You will have to think about the security implications. Be careful before doing something like 'Access-Control-Allow-Origin: *' This wont work on mobile browsers. In my experience they do not allow cross domain POST at all. I've tested android, iPad, iPhone There is a pretty big bug in FF < 3.6 where if the server returns a non 400 response code AND there is a response body (validation errors for example), FF 3.6 wont get the response body. This is a huge pain in the ass, since you cant use good REST practices. See bug here (its filed under jQuery, but my guess is its a FF bug - seems to be fixed in FF4). Always return the headers above, not just on OPTION requests. FF needs it in the response from the POST.
如果你可以访问跨域服务器,并且不想在服务器端做任何代码更改,你可以使用一个名为“xdomain”的库。
工作原理:
步骤1: 服务器1:包含xdomain库,并将跨域配置为从域:
<script src="js/xdomain.min.js" slave="https://crossdomain_server/proxy.html"></script>
步骤2: 在跨域服务器上,创建一个proxy.html文件,并将服务器1作为主服务器:
proxy.html:
<!DOCTYPE HTML>
<script src="js/xdomain.min.js"></script>
<script>
xdomain.masters({
"https://server1" : '*'
});
</script>
步骤3:
现在,您可以从server1对proxy.html作为端点进行AJAX调用。这是绕过CORS请求。图书馆内部使用iframe解决方案,它与凭证和所有可能的方法一起工作:GET, POST等。
查询ajax代码:
$.ajax({
url: 'https://crossdomain_server/proxy.html',
type: "POST",
data: JSON.stringify(_data),
dataType: "json",
contentType: "application/json; charset=utf-8"
})
.done(_success)
.fail(_failed)