JavaScript 跨域 POST 实现方案:基于 iframe 与 postMessage

作者:代码拾荒时间:2026-10-22 14:04:42浏览:542

JSONP 仅支持 GET 请求,本文介绍一种通过动态生成 iframe 内嵌表单实现 POST 跨域提交的方法。后端返回包含回调函数的脚本,前端通过 postMessage 接收响应数据,并简要提及来源验证的安全注意事项。

跨域 POST 挑战与解决方案概述

JavaScript 跨域是一个常见的开发场景,通常使用 JSONP 作为解决方案。然而,JSONP 机制仅支持 GET 请求,无法直接发送 POST 数据,这给需要提交敏感或大量数据的场景带来了不便。

为了解决这一问题,可以通过在隐藏的 iframe 中动态生成 HTML 表单并提交数据,利用 postMessage API 将后端返回的结果传递给主页面调用者。

后端 JSONP 接口实现

首先,需要实现一个能够接收 JSONP 格式请求的后端服务。后端语言的选择由开发者自行决定,关键在于正确解析回调参数并返回对应的脚本内容。

以 C# 为例,后端代码逻辑如下:


protected void Page_Load(object sender, EventArgs e)
    {
      StringBuilder sbRet = new StringBuilder();
      sbRet.Append("<script>");
      sbRet.Append(Request["jsoncallback"]);
      sbRet.Append("({");

      foreach (string k in Request.Form) {
        if (k == "jsoncallback") continue;
        sbRet.Append("'"+k+"':'"+Request.Form[k]+"'");
      }

      
      sbRet.Append("});");
      sbRet.Append("</script>");

      Response.Write(sbRet.ToString());
      Response.End();
    }

假设期望返回的数据结构为 { userName:'user1', password:'pass1' },当客户端访问 http://localhost/test?jsoncallback=callme 时,后端需识别 jsoncallback 参数。

后端实际应返回如下格式的脚本内容:<script>callme({ userName:'user1', password:'pass1' })</script>,从而完成 JSONP 的回调机制。

前端测试页面构建

接下来,在本地文件夹中构建一个用于测试的 HTML 页面,例如保存为 d:\test.html。


<form action="http://localhost/test" method="post">
  <input type="text" name="userName" value="user1" />
  <input type="text" name="password" value="pass1" />
  <input type="text" name="jsoncallback" value="callme" />
  <input type="submit" value="提交" />
</form>

第三步,浏览并点击提交,若返回 <script>callme({ userName:'user1', password:'pass1' })</script>,则说明后端程序正常。

通用封装代码与安全注意事项

随后,编写通用的 JavaScript 代码来封装上述 HTML 表单的生成与提交逻辑,以便在不同场景中复用。


<!doctype html>
<html>
  <head>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>测试一哈</title>
  </head>  
  <body>   
  <script>
  //源码 开始
   function postJSONP(url, data, callback) {
    var template = '<form action="{{url}}" method="post" id="form1">';   
    for (var k in data) {
     template = template
       + '  <input type="text" name="'+k+'" value="'+data[k]+'" />'
    }
      template = template 
      + '  <input type="text" name="jsoncallback" value="function callback(data) { parent.postMessage(data, \'*\'); } callback" />'
      + '</form>'
      + '<'+'script>'
      + 'document.getElementById("form1").submit();'
      + '</'+'script>';      
   template = template.replace("{{url}}", url);      
   var div = document.createElement("div");
   div.style.display = 'none';  
   div.innerHTML = '<iframe src=""></iframe>';
   document.body.appendChild(div);   
   var ifrm = div.children[0];
   var cwin = ifrm.contentWindow;
   cwin.document.write(template);   
   window.onmessage = function(e) {
   if (callback) callback(e.data);
   }
   }
   //源码 结束  
  //使用测试
   window.onload = function() {
   postJSONP('http://localhost:59898/WebForm1.aspx', { userName: '张静', password: '就不告诉你' }, function(data) {
    console.log(11, data);
   });

   postJSONP('http://localhost:59898/WebForm1.aspx', { 仓库: '1号大仓', 面积: '2万平米' }, function(data) {
    console.log(22, data);
   });
  }
 </script>
  </body>
</html>

此外,必须关注安全问题。


window.onmessage = function(e) {
  //可通过 e 来判断来源,并做一些安全方面的处理,此处读者自己去研究吧,可以加个 console.log(e) 看看 e 有哪些内容。
  if (callback) callback(e.data);
}

以上即为通过 iframe 和 postMessage 实现 JavaScript 跨域 POST 提交的完整流程,希望能为相关开发工作提供参考。

作者最新文章