如何在jsonp ajax调用中使用type: "POST"

55

我正在使用JQuery ajax jsonp。 我已经得到了以下JQuery代码:

 $.ajax({  
        type:"GET",        
        url: "Login.aspx",  // Send the login info to this page
        data: str, 
        dataType: "jsonp", 
        timeout: 200000,
        jsonp:"skywardDetails",
        success: function(result)
        { 
             // Show 'Submit' Button
            $('#loginButton').show();

            // Hide Gif Spinning Rotator
            $('#ajaxloading').hide();  
         } 

    });  

上述代码运行良好,我只想将请求方式从"GET"更改为"POST",请建议如何实现。

谢谢

6个回答

88

您无法使用JSONP进行POST请求......因为这种方式根本行不通,它创建了一个<script>元素来获取数据......而且必须是GET请求。 除了将数据POST到自己的域作为代理之外,您并没有太多选择......但用户无法直接执行此操作并看到响应。


1
@MKS - 你实际上不能这样做,除非通过自己的域名代理...GET请求本质上是“开放”的,比POST更加“开放”。 - Nick Craver
谢谢@NICK,你觉得使用“GET”而不是“POST”安全吗?使用“GET”的缺点有哪些?请给予建议。 - Manoj Singh
1
@T.J. - 嗯,如果你的有效负载在POST而不是URL中,那么使用SSL可以大大提高安全性,这正是我所追求的。 - Nick Craver
@MKS - 如果你正在做一些安全相关的事情,首先使用SSL。如果没有这个,页面需要数据吗?一个有点hacky的<iframe>解决方案可能是唯一的选择。 - Nick Craver
4
在传输过程中,GET请求通过SSL的安全性不低于POST请求,认为GET请求不安全是错误的。HTTP请求中的URL信息(如路径、查询字符串等)都会被加密,因此你的查询字符串在数据包级别上是无法被“嗅探”的。然而,仍有其他需要注意的问题,详见这篇SO问答 - Sean
显示剩余5条评论

41

使用dataType中的json,并像这样发送:

使用dataType中的json,并像这样发送:

    $.ajax({
        url: "your url which return json",
        type: "POST",
        crossDomain: true,
        data: data,
        dataType: "json",
        success:function(result){
            alert(JSON.stringify(result));
        },
        error:function(xhr,status,error){
            alert(status);
        }
    });

并将以下这些行放在你的服务器端文件中:

如果是 PHP:

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Max-Age: 1000');

如果Java:

response.addHeader( "Access-Control-Allow-Origin", "*" ); 
response.addHeader( "Access-Control-Allow-Methods", "POST" ); 
response.addHeader( "Access-Control-Max-Age", "1000" );

另一个回答解释了这段代码的原因:https://dev59.com/2G855IYBdhLWcg3wJgxy#4528304 - igorsantos07
1
@PratikButani 很棒的回答。 - Muhammad
2
允许任何第三方站点通过这些响应头设置向您的站点应用程序发起AJAX调用,是否存在潜在的安全影响(例如CSRF)? - Jon Schneider
1
这在我使用Chrome v.36.0.1985.125时没有起作用。我收到了错误标准-没有“Access-Control-Allow-Origin”头,即使我在PHP中有它,并且可以在网络选项卡中的检索文件的标题下看到它。当使用“GET”时,完全相同的请求有效。我尝试了许多排列组合,所以如果您想使用这个答案,我会担心它可能不适用于所有浏览器。 - Luke
2
请注意,jsonp 的部分目的是让浏览器能够发送 cookies。这里的代码将无法实现该功能。为此,您可能需要按照此文档打开凭据:https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials - ragamufin
如果我们正在使用ASP.NET C#呢?说真的,我已经卡在这一步上很久了,我无法超越它,我快要疯了! :) - user1786794

7
现代浏览器允许跨域AJAX查询,这被称为跨源资源共享(有关更短和更实用的介绍,请参见此文档),最近版本的jQuery支持它。但是您需要一个相对较新的浏览器版本(FF3.5+,IE8+,Safari 4+,Chrome4+;没有Opera支持)。

1
只是挑刺一下,JSONP 不是 AJAX。 - Tgr
5
实际上,我会挑剔一下,并且说JSONP不是XMLHttpRequest,而是AJAX。无论如何,AJAX的定义已经不太清晰,因为它严格来说并没有涵盖获取JSON而非XML或同步获取的情况。因此,考虑到AJAX已经被广泛地应用于比其定义更广的范围内,再加上JSONP通常与异步JavaScript一起使用,我非常乐意说AJAX也包括JSNOP。 - hippietrail
这里重要的部分似乎是设置一个 Access-Control-Allow-Origin: * 或类似的 HTTP 标头。(您可以声明单个允许的来源) - jocull
1
但是您仍然[传统上]只能使用GET而不能使用POST来进行JSONP请求,对吗?也就是说,我不明白这个答案如何回答OP的问题。只是,如果您必须使用POST(这可能是“真正”的问题),那么您有其他选项可以选择,而不是JSONP? - ruffin
如果你和我一样,想知道如何实现这个功能,请查看同一个问题中的其他答案:https://dev59.com/2G855IYBdhLWcg3wJgxy#17722058 - igorsantos07


0

如果您只想使用$.ajax()向自己的站点进行表单POST(例如模拟AJAX体验),那么您可以使用jQuery Form Plugin。但是,如果您需要向不同域或者使用不同协议(非安全的http:页面发布到安全的https:页面)的自己的域提交表单,则会遇到跨域脚本限制,这些限制无法仅通过jQuery解决(更多信息)。在这种情况下,您需要动用强大的工具:YQL。简而言之,YQL是一种具有类似SQL语法的Web抓取语言,允许您将整个互联网作为一个大表进行查询。就我而言,YQL现在是唯一[容易]的方法,如果您希望使用客户端JavaScript进行跨域表单POST。

更具体地说,您需要使用YQL的Open Data Table,其中包含一个Execute块来实现此目的。关于如何做到这一点的良好概述,请阅读文章“使用YQL抓取需要POST数据的HTML文档”。幸运的是,YQL大师Christian Heilmann已经创建了一个处理POST数据的Open Data Table。您可以在YQL控制台上尝试使用Christian的“htmlpost”表。以下是YQL语法的详细说明:
  • select * - 选择所有列,类似于SQL,但在这种情况下,列是查询返回的XML元素或JSON对象。在爬取网页的上下文中,这些“列”通常对应于HTML元素,因此如果只想检索页面标题,则应使用select head.title
  • from htmlpost - 要查询的表;在这种情况下,使用“htmlpost”开放数据表(如果此表不适合您的需求,可以使用自定义表)。
  • url="..." - 表单的action URI。
  • postdata="..." - 序列化的表单数据。
  • xpath="..." - 您要包含在响应中的节点的XPath。这充当过滤机制,因此如果要仅包括<p>标记,则应使用xpath="//p";要包括所有内容,应使用xpath="//*"

点击“测试”以执行YQL查询。一旦您对结果满意,请确保(1)单击“JSON”以将响应格式设置为JSON,以及(2)取消选中“诊断”,通过删除多余的诊断信息来最小化JSON负载的大小。最重要的是页面底部的URL - 这是您在$.ajax()语句中使用的URL。

在这里,我将向您展示使用此示例表单通过YQL查询执行跨域表单POST的确切步骤:

<form id="form-post" action="https://www.example.com/add/member" method="post">
  <input type="text" name="firstname">
  <input type="text" name="lastname">
  <button type="button" onclick="doSubmit()">Add Member</button>
</form>

你的JavaScript代码应该长这样:

function doSubmit() {
  $.ajax({
    url: '//query.yahooapis.com/v1/public/yql?q=select%20*%20from%20htmlpost%20where%0Aurl%3D%22' +
         encodeURIComponent($('#form-post').attr('action')) + '%22%20%0Aand%20postdata%3D%22' +
         encodeURIComponent($('#form-post').serialize()) +
         '%22%20and%20xpath%3D%22%2F%2F*%22&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=',
    dataType: 'json', /* Optional - jQuery autodetects this by default */
    success: function(response) {
      console.log(response);
    }
  });
}

url 字符串是从 YQL 控制台复制的查询 URL,除了表单编码的 action URI 和序列化输入数据动态插入。

注意:在通过互联网传递敏感信息时,请注意安全性影响。确保您正在提交敏感信息的页面是安全的 (https:) 并且 使用 TLS 1.x 而不是 SSL 3.0


-1

这是我编写的JSONP,与大家分享:

发送请求的页面
http://c64.tw/r20/eqDiv/fr64.html

请自行将下面的SREC保存为.html文件
c64.tw/r20/eqDiv/src/fr64.txt
响应页面,请将下面的SREC保存为.jsp文件
c64.tw/r20/eqDiv/src/doFr64.txt

或者将代码嵌入您的页面中:

function callbackForJsonp(resp) {

var elemDivResp = $("#idForDivResp");
elemDivResp.empty();

try {

    elemDivResp.html($("#idForF1").val() + " + " + $("#idForF2").val() + "<br/>");
    elemDivResp.append(" = " + resp.ans + "<br/>");
    elemDivResp.append(" = " + resp.ans2 + "<br/>");

} catch (e) {

    alert("callbackForJsonp=" + e);

}

}

$(document).ready(function() {

$(document).ready(function() {

var testUrl = "http://c64.tw/r20/eqDiv/doFr64.jsp?callback=?";

$(document.body).prepend("post to " + testUrl + "<br/><br/>");

$("#idForBtnToGo").click(function() {

    $.ajax({

        url : testUrl,
        type : "POST",

        data : {
            f1 : $("#idForF1").val(),
            f2 : $("#idForF2").val(),
            op : "add"
        },

        dataType : "jsonp",
        crossDomain : true,
        //jsonpCallback : "callbackForJsonp",
        success : callbackForJsonp,

        //success : function(resp) {

        //console.log("Yes, you success");
        //callbackForJsonp(resp);

        //},

        error : function(XMLHttpRequest, status, err) {

            console.log(XMLHttpRequest.status + "\n" + err);
            //alert(XMLHttpRequest.status + "\n" + err);

        }

    });

});

});


我尝试过这个,所有数据都作为 $_GET 参数在服务器上(php)接收。 - Dika
好的,我已经修复了网址链接(http://c64.tw/r20/eqDiv/fr64.html),请再试一次。谢谢。 - user7420965

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接