如何通过JavaScript发送跨域POST请求?

如何通过JavaScript发送跨域POST请求?,javascript,ajax,cross-domain,Javascript,Ajax,Cross Domain,如何通过JavaScript发送跨域POST请求 注意-它不应该刷新页面,我需要抓取并解析之后的响应 创建一个iFrame 在表单中添加隐藏的输入 将表单的操作设置为URL 将iframe添加到文档 提交表格 伪码 var ifr = document.createElement('iframe'); var frm = document.createElement('form'); frm.setAttribute("action", "yoururl"); frm.setAttrib

如何通过JavaScript发送跨域POST请求

注意-它不应该刷新页面,我需要抓取并解析之后的响应

  • 创建一个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的样式,使其隐藏并绝对定位。不确定浏览器是否允许跨站点发布,但如果允许,这就是如何做到的。

    高级。。。。您需要在服务器上设置cname,以便other-service.your-server.com指向other-server.com

    您的页面动态创建一个不可见的iframe,它充当您到other-server.com的传输。然后,您必须通过JS从您的页面与other-server.com进行通信,并通过回调将数据返回到您的页面


    可能,但需要您的-server.com和其他server.com的协调

    检查中的
    post\u方法
    功能-这是上述iframe方法的一个很好的示例

  • 创建两个隐藏的iFrame(在css样式中添加“display:none;”)。让你的第二个iframe指向你自己领域中的某个东西

  • 创建一个隐藏表单,将其方法设置为“post”,目标=您的第一个iframe,并可选地将enctype设置为“multipart/form data”(我认为您希望进行post,因为您希望发送多部分数据,如图片?)

  • 准备好后,将表单提交到帖子中

  • 如果您可以让另一个域返回javascript,该javascript将与Iframes()进行跨域通信,那么您就很幸运了,您也可以捕获响应


  • 当然,如果您想将服务器用作代理,可以避免所有这些。只需将表单提交到您自己的服务器,该服务器将代理请求到另一台服务器(假设另一台服务器未设置为注意IP差异),获取响应,然后返回您喜欢的任何内容。

    使用YQL自定义表+JS XHR,应该可以查看:

    我用它来做一些客户端(js)html抓取,效果很好
    (我有一个完整的音频播放器,可以在互联网上搜索/播放列表/歌词/最后的fm信息,所有客户端都是js+YQL)

    这是一个老问题,但一些新技术可能会帮助某些人

    如果您对另一台服务器具有管理权限,那么您可以使用OpenSourceForge项目来完成跨域发布。Forge提供了一个跨域JavaScript XmlHttpRequest包装器,它利用了Flash的原始套接字API。这篇文章甚至可以通过TLS完成

    您需要对要发布到的服务器进行管理访问的原因是,您必须提供允许从域进行访问的跨域策略


    如果您可以访问所有涉及的服务器,请在其他域中请求的页面的回复标题中添加以下内容:

    PHP:

    例如,在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;
    }
    
    函数xmlrpc_服务器_输出($xml){
    $xml=''。\n..$xml;
    标题(“连接:关闭”);
    标题('Content-Length:'.strlen($xml));
    标题('Access-Control-Allow-Origin:');
    标题('Content-Type:application/x-www-form-urlencoded');
    标题(‘日期:’。日期(‘r’);
    //$xml=str_replace(“\n”,”,$xml);
    echo$xml;
    出口
    }
    

    这可能会造成安全问题,您应该确保采取适当的措施来验证请求。

    如果您控制远程服务器;IE8及以上版本以及FF、GC和Safari的所有最新版本都支持它。(但在IE8和IE9中,CORS不允许您在请求中发送cookie。)

    因此,如果您不控制远程服务器,或者如果您必须支持IE7,或者如果您需要cookie并且必须支持IE8/9,那么您可能需要使用iframe技术

  • 创建具有唯一名称的iframe。(iFrame对整个浏览器使用全局名称空间,因此请选择其他网站不会使用的名称。)
  • 以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();
    }
    
    当心!您将无法直接读取帖子的响应,因为iframe存在于单独的域中。帧不允许从不同的域相互通信;这是最新的


    如果您控制远程服务器,但无法使用CORS(例如,因为您在IE8/IE9上,需要使用Cookie),则有一些方法可以绕过同一源策略,例如使用和/或多个库中的一个库,允许您在较旧的浏览器中发送跨域跨帧消息:


    如果不控制远程服务器,则无法读取POST的响应。否则会导致安全问题。

    更新:在继续之前,每个人都应该阅读并理解CORS上的内容。这很容易理解,也很清楚

    如果您控制要发布的服务器,只需通过在服务器上设置响应头来利用“跨源资源共享标准”。这个答案在本帖的其他答案中讨论过,但在我看来不是很清楚

    简而言之,这里是如何完成从from.com/1.html到to.com/postHere.php的跨域POST(以php为例)。注意:对于非
    选项
    请求,您只需设置
    访问控制允许源代码
    ——此示例始终为较小的代码段设置所有标题

  • 在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;
    }
    
    这允许脚本进行跨域POST、GET和选项。当你继续阅读时,这一点会变得清晰

  • 从JS设置跨域帖子(jQuery示例):

    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; }
    $.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.');
        }
    });
    
    $.ajax({
        type     : 'POST',
        dataType : 'json', 
        url      : 'another-remote-server',
        ...
    });
    
    <?
    
    function post($url, $data) {
    $header = array("User-Agent: " . $_SERVER["HTTP_USER_AGENT"], "Content-Type: application/x-www-form-urlencoded");
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_POST, 1);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    $response = curl_exec($curl);
    curl_close($curl);
    return $response;
    }
    
    $url = "your cross domain request here";
    $data = $_SERVER["QUERY_STRING"];
    echo(post($url, $data));
    
    $.ajax({
    type: 'POST',
    url: 'submit.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.');
    }
    });
    
      <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>
    
    [HttpPost]
    public JsonResult Save()
    {
        //Handle the post data...
    
        return Json(
            new
            {
                IsSuccess = true
            });
    }
    
    $.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
            }
        });
    
    var win = $('iframe')[0].contentWindow
    
    function get(event) {
        if (event.origin === "http://reciver.com") {
            // event.data is response from POST
        }
    }
    
    if (window.addEventListener){
        addEventListener("message", get, false)
    } else {
        attachEvent("onmessage", get)
    }
    win.postMessage(JSON.stringify({url: "URL", data: {}}),"http://reciver.com");
    
    function listener(event) {
        if (event.origin === "http://sender.com") {
            var data = JSON.parse(event.data);
            $.post(data.url, data.data, function(reponse) {
                window.parent.postMessage(reponse, "*");
            });
        }
    }
    // don't know if we can use jQuery here
    if (window.addEventListener){
        addEventListener("message", listener, false)
    } else {
        attachEvent("onmessage", listener)
    }
    
    $.ajax({
            type: "POST",
            url: "http://www.yoururl.com/",
            crossDomain: true,
            data: 'param1=value1&param2=value2',
            success: function (data) {
                // do something with server response data
            },
            error: function (err) {
                // handle your error logic here
            }
        });
    
    catta('./data/simple.json').then(function (res) {
      console.log(res);
    });
    
    <script src="js/xdomain.min.js" slave="https://crossdomain_server/proxy.html"></script>
    
    proxy.html:
    <!DOCTYPE HTML>
    <script src="js/xdomain.min.js"></script>
    <script>
      xdomain.masters({
        "https://server1" : '*'
      });
    </script>
    
    $.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)