【问题标题】:Cross-site AJAX requests跨站 AJAX 请求
【发布时间】:2010-09-24 21:57:01
【问题描述】:

我需要从一个网站向另一个域中托管的 REST Web 服务发出 AJAX 请求。

虽然这在 Internet Explorer 中运行良好,但 Mozilla 和 Google Chrome 等其他浏览器施加了更严格的安全限制,禁止跨站点 AJAX 请求。

问题是我无法控制该站点所在的域或 Web 服务器。这意味着我的 REST Web 服务必须在其他地方运行,并且我无法设置任何重定向机制。

这是进行异步调用的 JavaScript 代码:

var serviceUrl = "http://myservicedomain";
var payload = "<myRequest><content>Some content</content></myRequest>";
var request = new XMLHttpRequest();
request.open("POST", serviceUrl, true); // <-- This fails in Mozilla Firefox amongst other browsers
request.setRequestHeader("Content-type", "text/xml");
request.send(payload);

如何在 Internet Explorer 以外的其他浏览器中使用此功能?

【问题讨论】:

  • @PhiLho 在这种情况下,我的目标是调用托管在不同域上的 REST 服务,不包括动态内容。

标签: javascript ajax security xss


【解决方案1】:

也许JSONP 可以提供帮助。

注意,您必须将消息更改为使用 json 而不是 xml

编辑

flickr 和twitter 等主要网站都支持带有回调等的 jsonp

【讨论】:

  • 这可能行得通,但 JSONP 承认出了点问题 :)
  • 这种方法有多受欢迎?这似乎有点实验性。
  • @annakata 显然,但他提到他无法处理 Web 服务器等,因此使用代理是不可能的。我不是来评论他的情况,只是为他的问题/问题提供可能的解决方案。
  • @redsquare:同意,他在角落里@enrico:相当实验,但它被使用了
  • 即使从托管在与 REST 服务相同的域上的 iframe 发布 AJAX 请求是一个可行的解决方案(只要 iframe 和页面之间不需要通信),我'由于兼容性问题,我一般不太喜欢 iframe。所以 JSONNP 可能是目前最好的解决方案。
【解决方案2】:

标记为答案的帖子是错误的:iframe 文档无法访问父级。同源策略双向起作用。

事实上,不可能以任何方式使用 xmlhttprequest 来使用基于 rest 的 web 服务。从不同域(没有任何框架)加载数据的唯一方法是使用 JSONP。任何其他解决方案都需要位于您自己域中的服务器端代理,或位于远程域中的客户端代理和某种跨站点通信(如easyXDM)来在文档之间进行通信。

【讨论】:

  • -1 因为这不是不准确的。通过使用“父”DOM 对象,可以使用 JavaScript 从 IFRAME 访问父页面。例如,这将从 IFRAME 中修改页面中的元素: parent.document.getElementById("someDiv").innerHTML = "some content";
  • 问题是关于来自不同域的文档 - 因此相同的来源策略将生效。如果父级来自 domainB,则来自 domainA 的 IFrame 无法访问其父级的 contentDocument。作为easyXSS跨站库的作者,我确实对这方面有所了解。
  • 我当时误解了你的回答。您是对的,当两者托管在不同的域中时,iframe 无法访问父页面的内容,反之亦然。但是在我的情况下,使用 iframe 效果很好,因为它不需要以任何方式访问父页面,而只是将 AJAX 请求发布到托管在同一域上的服务。
  • 您需要编辑您的答案,因为 SO 不允许我更改太旧的投票
  • easyXSS 改名为easyXDM,也做了不小的改进
【解决方案3】:

这在 IE 中有效的事实是 IE 的安全问题,而不是功能。

不幸的是,跨站点脚本是被禁止的,并且可以接受的解决方法是通过您自己的域代理请求:您真的没有能力添加或修改服务器端代码吗?

此外,次要解决方法 - 涉及通过脚本标签获取数据 - 仅支持 GET 请求,您可能可以使用 SOAP 服务破解该请求,但对于 RESTful 服务的 POST 请求则没有那么多你描述的。

我真的不确定是否存在 AJAX 解决方案,您可能会回到

解决方案。

【讨论】:

  • 我同意允许 XSS 是 IE 中的一个安全漏洞。不幸的是,我无法控制 Web 服务器,因为它是托管在第三方提供商上的博客。我也考虑过使用 HTML 表单,但这会导致整页发布,而不是很好的异步调用。
【解决方案4】:

不太明确的解决方法(但有效)是使用 iframe 作为向其他网站发出请求的容器。问题是,父级无法访问 iframe 的内容,只能导航 iframe 的“src”属性。但是 iframe 内容可以访问父级的内容。

所以,如果 iframe 的内容知道,他们可以调用父页面中的一些 javascript 内容或直接访问父页面的 DOM。

编辑: 示例:

function ajaxWorkaroung() {
    var frm = gewtElementById("myIFrame")
    frm.src = "http://some_other_domain"
}
function ajaxCallback(parameter){
    // this function will be called from myIFrame's content
}

【讨论】:

  • IFrame 比 ajax 慢,而且在旧版 IE 中,我记得每次 iframe.src 更新都会播放“点击”声音:(
  • 在 javascript 中无法访问父 javascript 数据或函数跨域。答案是不真实的。
  • @nagtur:我前段时间成功使用过这个场景:|。
【解决方案5】:

让您的服务域接受跨域资源共享 (CORS)。

典型场景:大多数兼容 CORS 的浏览器会首先发送一个 OPTIONS 标头,服务器应向该标头返回有关接受哪些标头的信息。如果标头满足服务对所提供请求的要求(允许的方法为 GET 和 POST、Allowed-Origin * 等),则浏览器将使用适当的方法(GET、POST 等)重新发送请求。

这里的所有内容都与您使用 IE 时的相同,或者更简单地说,如果您发布到同一个域。

注意事项:某些服务开发 SDK(尤其是 WCF)会尝试处理请求,在这种情况下,您需要预处理 OPTIONS 方法以响应请求并避免该方法在服务器上被调用两次。

简而言之,问题出在服务器端。

编辑 IE 9 及更低版本的 CORS 存在一个问题,即它没有完全实现。幸运的是,您可以通过从服务器端代码调用服务并让它通过您的服务器返回来解决这个问题(例如 mypage.aspx?service=blah&method=blahblah&p0=firstParam=something)。从这里开始,您的服务器端代码应该实现请求/响应流模型。

【讨论】:

    【解决方案6】:

    只需在您的源域上使用服务器端代理即可。这是一个例子:http://jquery-howto.blogspot.com/2009/04/cross-domain-ajax-querying-with-jquery.html

    【讨论】:

      【解决方案7】:

      这也可以使用本地网络服务器设置来完成,该本地设置使用正确的参数调用 curl 并返回 curl 输出。

      app.rb

      require 'sinatra'
      require 'curb'
      
      set :views,lambda {"views/"+self.name.to_s.downcase.sub("controller","")}
      set :haml, :layout => :'../layout', :format => :html5, :escape_html=>true
      disable :raise_errors
      
      get '/data/:brand' do
        data_link =  "https://externalsite.com/#{params[:brand]}"
        c = Curl::Easy.perform(data_link)
        c.body_str
      end
      

      向 localhost:4567/data/something 发送 ajax 请求将从 externalsite.com/something 返回结果。

      【讨论】:

        【解决方案8】:

        另一种选择是在您自己的域上设置 CNAME 记录以“屏蔽”远程域主机名。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-03-06
          • 1970-01-01
          • 1970-01-01
          • 2015-10-06
          • 2023-04-05
          • 2012-04-15
          相关资源
          最近更新 更多