将静态内容与 Web 服务托管在不同的域上,如何避免跨域?

Posted

技术标签:

【中文标题】将静态内容与 Web 服务托管在不同的域上,如何避免跨域?【英文标题】:Hosting static content on different domain from webservices, how to avoid cross-domain? 【发布时间】:2012-04-02 12:39:24 【问题描述】:

我们最近一直在开发一个相当现代的网络应用程序,并准备将其部署为 alpha/beta 版并获得一些实际体验。

我们有基于 ASP.Net 的 Web 服务 (Web Api) 和一个 javascript 前端,它是 100% 使用主干的客户端 MVC。

我们已经购买了我们的域名,为了这个问题,我们的部署如下所示:

webservices.mydomain.com(网络服务)

mydomain.com(JavaScript 前端)

如果 JavaScript 尝试与子域上的 web 服务通信,我们会遇到跨域问题,我已经玩过 CORS,但对跨浏览器支持不满意,所以我把它算作一个选项。

在我们的开发 PC 上,我们使用 IIS 反向代理将所有对 mydomain.com/webservices 的请求转发到 webservices.mydomain.com - 这解决了我们的所有问题,因为浏览器认为所有内容都在同一个域中。

所以我的问题是,在公共部署中,这个问题最常如何解决?反向代理是正确的方法吗?如果是这样,是否有任何托管服务为这种情况提供反向代理?有没有更好的部署方法?

我想使用 CloudFront CDN,因为我们所有的服务器/服务都由 Amazon 托管,但我真的很难找到有关 CDN 是否可以支持这种设置的信息。

谢谢

【问题讨论】:

也许我个人的实现太简单了(如果是这样我也会对其他人的 cmets 感兴趣)。我想缺少的是您在前/后之间的数据传输是什么?在我的简单实现中,前端通过 JSONP 与后端(WCF 服务)通信,实现“真正的”跨域实现。如果我需要“代理”,那么它是一个“应用代理”——mydomain.com 的前端将与 mydomain.com 上的处理程序(即 ashx)对话,该处理程序将 http 请求“代理”到 myotherdomain.com 上的 WCF。跨度> 您使用的是 JQuery 还是纯 javascript? (如果是 JQuery,你可以使用这个:usejquery.com/posts/the-jquery-cross-domain-ajax-guide) 对于 WebAPI,您可以查看这篇关于使用 JSONP 启用 CORS 的帖子,它应该可以在浏览器中正常工作 goo.gl/KjT6y 【参考方案1】:

您正在尝试做的是跨子域调用,而不是完全跨域。 这就是技巧:http://www.tomhoppe.com/index.php/2008/03/cross-sub-domain-javascript-ajax-iframe-etc/

如被问及此问题最常见的解决方法。我的回答是:这个问题通常是避免的。在现实世界中,您将设置您的域,例如您不需要为了让您的应用程序运行或设置代理服务器来为您转发呼叫而采取这种方式。 JSONP 也是一种 hack-ish 解决方案。

【讨论】:

出于好奇,我将如何设置我的域以避免此问题?在我看来,“网络应用程序”还没有为黄金时间做好准备,即你还不能构建和运行一个纯 JavaScript 网络应用程序。 CORS = 不良支持,JSONP = Hack/Limited 功能,Inter-iframe coms = Hack。 只需使用带有反向代理的负载均衡器将您的 Web 服务设置为 mydomain.com/service,所有问题都解决了。【参考方案2】:

您可以简单地将 JSONP 用于 AJAX 请求,然后跨域就不是问题了。

如果 AJAX 请求返回一些 html,它可以转义为 JSON 字符串。

不过,第二个有点尴尬。

【讨论】:

【参考方案3】:

你有 2/3 层

在网络服务代码隐藏类中,添加此属性:<System.Web.Script.Services.ScriptService()> _

也许您需要在 web.config 的 System.web 节点中添加它:

<webServices>
        <protocols>
          <add name="AnyHttpSoap"/>
          <add name="HttpPost"/>
          <add name="HttpGet"/>
        </protocols>
      </webServices>

在客户端界面中

-在子域上添加对服务的 Web 引用(例如 webservices.mydomain.com/svc.asmx) Visual Studio 制作“代理类”

-在母版页的|页面|控件的代码后面添加功能 - 只需从客户端调用此函数

您可以将 AJAX 功能与 scriptmanager 一起使用,也可以使用 JQuery 等其他系统。

如果您的主网站是在 .NET 3.5 或更早版本中编译的,您需要添加对命名空间 System.Web.Extensions 的引用并在您的 web.config 文件中声明它。

【讨论】:

【参考方案4】:

如果您有足够的带宽(网络 I/O 和 CPU)来处理这个问题,反向代理是一个很好的解决方案。一个好的反向代理甚至会缓存静态调用,以帮助减轻代理引入的网络延迟。

另一个选项是设置正确的跨域策略文件和/或标头。在某些云提供商中这样做可能很困难,甚至是不可能的。我最近遇到了字体文件和 IE 对跨域调用不满意的问题。我们无法获得用于设置正确标头的云存储提供商,因此我们将它们托管在本地,而不必处理反向代理。

【讨论】:

【参考方案5】:

要允许使用 ASP.NET AJAX 从脚本调用此 Web 服务,请将以下行添加到第一个 Web 服务代码隐藏:

[System.Web.Script.Services.ScriptService]

【讨论】:

【参考方案6】:

easyXDM 是一个值得探索的跨域 Javascript 插件。它在浏览器支持标准时使用标准,并在浏览器不支持标准时抽象出所需的各种 hack。来自easyXDM.net:

easyXDM 是一个 Javascript 库,可让您作为开发人员 轻松解决同源设置的限制 政策,反过来又使交流和公开 javascript 变得容易 API 跨域边界。

easyXDM 的核心提供了一个能够通过 两个窗口之间基于字符串的消息,一个消费者(主要 文档)和提供者(使用 iframe 包含的文档)。它 通过使用几种可用技术中的一种来做到这一点,总是 为当前浏览器选择最有效的一种。对所有人 实现传输堆栈提供双向性, 可靠性、排队和发件人验证。

easyXDM 的目标之一是支持所有浏览器 共同使用,并为所有人提供相同的功能。中的一个 实现这一目标的策略是遵循既定标准,另外 使用特征检测来确保使用最有效的。

引用easy XDM的作者的话:

...LinkedIn、Twitter 和 Disqus 等网站以及应用程序运行 诺基亚和其他公司已经在 easyXDM 提供的消息传递框架。

所以 easyXDM 显然不是什么小技巧,但我承认它对你的项目有很大的依赖性。

Web 的当前状态是,如果你想推信封,你必须使用特征检测和 polyfill,或者干脆强制你的用户升级到 HTML5 浏览器。如果这让您感到不安,那么您并不孤单,但 polyfill 是一种暂时的邪恶,需要从网络的位置到达我们希望的位置。

另见this SO question。

【讨论】:

以上是关于将静态内容与 Web 服务托管在不同的域上,如何避免跨域?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Firefox 中的网络字体不能在不同的域上工作?

托管在不同域上的 JavaScript 可以读取/修改另一个域的 DOM 吗?

告诉另一个域上的控制器有新数据

如何在 firebase 托管中托管单页 webapp 的静态文件,并将 web API 部署在不同的服务器中

仅在特定域上加载 iframe

ajax跨域问题-web开发必会