浏览器向另一台服务器发送的HTTP POST请求

3
我正在尝试实现这个http://wiki.kolmisoft.com/index.php/MOR_API_login。我已经在服务器上启用了API设置。问题出在Javascript上,我的主网站运行在域名website.com下,而Asterisk服务器运行在voip.website.com下。因此,当我尝试使用jQuery调用该URL时,我会得到XMLHttpRequest无法加载http://voip.website.com/.../.../..... 源http://sites不允许访问。

我不确定最好的解决方法是什么。任何建议都将非常有帮助。

2个回答

4

所有浏览器都执行同源策略,包括整个主机(website.com与voip.website.com)。除非主机相同,否则您无法处理从Ajax post返回的JSON。

有一种名为JSONP的解决方法。诀窍在于将回复包装在JavaScript函数中。您看,同源策略仅适用于数据,而不是完整的脚本本身。因此,如果响应是JavaScript而不是数据,则浏览器认为您需要运行此脚本。

例如,假设您的响应将是以下JSON:

{
  firstName: 'Abed',
  lastName: 'Nadir',
  school: 'Greendale Community College'
}

相反,您可以这样回复:
({
  firstName: 'Abed',
  lastName: 'Nadir',
  school: 'Greendale Community College'
})

需要翻译的内容:

需要注意的是括号前后将其变成了JavaScript匿名函数而不是JSON数据。你所需要做的就是接收响应并去掉前后的JavaScript代码。

听起来有些笨拙?确实如此,但包括Flickr、Google、Amazon、Facebook等在内的所有人都在这样做。


2
您需要使用JSONP对数据进行包装,并将其作为text/javascript的MIME类型传输,以绕过跨域策略。 有哪些使用JSONP与.net交互的JQuery好例子? 标题提到了.net,但服务器端环境与客户端实现无关。
一个可行的替代方案是在您自己的域上设置一个服务器端脚本,该脚本将使用CURL(或任何其他http lib)转发请求,然后将响应输出到脚本的XHR请求。这种方法在您的客户端脚本和您正在尝试访问的远程域之间设置了一个catchall,因为curl或任何其他服务器端http lib不受跨域策略的限制。 编辑 我要详细介绍一下我的第二种方法,因为你说你需要发送一个post。作为概念证明,我将使用PHP来详细说明需要做什么,但将这个通用想法移植到另一种脚本语言应该很简单。
假设我可以在你的域名下 www.yourdomain.com/data.php 创建一个通用脚本。该文件中的逻辑需要从 HTTP 请求中读取所有我的 post 变量,将它们放入一个 curl 实例中作为对新域的请求,执行该请求,然后将该请求的响应输出回我的 ajax XHR 中,以便第一次没有中介就像原来一样。我喜欢使用 jscol's OOCurl 来使 curl 的语法更加美观。
<?
reqire_once('path/to/oocurl.php');
$c = new Curl('voip.otherdomain.com/api'); // instantiate with the url endpoint for the api
$c->post = True;
// Set the postfields for the child request to the same as the parent
$c->postfields = $_POST;
//Bust if there is an error and output that instead  
$c->failoneerror = True;
$response = $c->exec();
if($c->errno()){
  //there was an error, what was it?
  header('Status:' . $c->info(CURLINFO_HTTP_CODE));
  echo $c->error();
}else{
  //success, echo output
  header('Content-type: application/json');
  echo $response;
}
?>

将您的ajax请求发送到这种类型的脚本将透明地将它们移交给在CURL构造函数中指定的其他域。请注意,我假设返回的MIME类型为json-您可能需要调整此设置以适应您的API。
如果您有用于API的身份验证凭据,则需要手动将它们编码为附加的post变量,并使用hmac保护端点。这确实取决于您如何进行客户端/服务器端交互,有点超出了重定向器的范围...基本上只需确保定义了服务器哈希盐并且将摘要与您的post请求一起发送,以确保第三方无法简单地发布到您的中介端点。
编辑
如果有人从Google跌入,请注意,我制作了一个库,其中包含我的方法here.

在我目前的情况下,我必须使用JSONP调用HTTP POST。但是该文章提到,不能使用JSONP发出POST请求。我的理解正确吗?https://dev59.com/_W865IYBdhLWcg3wWtKz - BTR Naidu
那么你唯一的选择就是采用我所描述的第二种方法,因为你正在尝试通过ajax将数据发送到API而不是获取它。你是否有能力在你的环境中部署某种脚本(例如你拥有ssh/ftp访问权限和类似LAMP堆栈的安装)? - DeaconDesperado
我对系统有完全的控制权,但系统本身是使用RoR开发的,我不想在那里瞎弄。正如维基中所述,我希望在成功登录尝试后进行重定向。我尝试了第二种方法,但我面临的问题是,在成功登录后,voip.website.com返回了被ajax捕获的登录后页面。现在我被困在这里...如何告诉ajax用新页面的内容覆盖当前页面?嗯...也许我不应该在这里使用ajax...必须尝试其他方法...? - BTR Naidu
感谢提供详细信息。我会尝试使用您的示例代码,并在进展时向您更新。 - BTR Naidu
提议的解决方案对我有效,但我正在使用ajax调用php,在从voip.website.com获得良好响应后,页面不会重定向。有什么线索可以修复这个问题吗? - BTR Naidu
我建立了一个库来帮助使用CURL进行此操作。随意使用。https://github.com/DeaconDesperado/forwardr - DeaconDesperado

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