来自非安全页面的安全 xmlhttprequest

Posted

技术标签:

【中文标题】来自非安全页面的安全 xmlhttprequest【英文标题】:secure xmlhttprequest from nonsecure page 【发布时间】:2011-02-24 22:57:07 【问题描述】:

我想通过在非安全页面 (http://site.com/page.htm) 内运行的 javascript 向安全 uri (https://site.com/ajaxservice/) 发出 XMLHttpRequest。我已经尝试过各种疯狂的东西,比如 iframe 和动态脚本元素,但到目前为止还没有。我知道我违反了“同源政策”,但必须有某种方法可以使这项工作发挥作用。

除了用 javascript 编写 SSL 协议之外,我会采用任何古怪的解决方案。

【问题讨论】:

+1 甚至考虑用 JavaScript 编写 SSL! 我认为这是不可能的。以前问过:***.com/questions/1105934/ajax-http-https-problem 使用 iframe 和书签哈希可能有点可能,但这很难看,只有当哈希后的部分没有发送到服务器时才安全。 陈旧,该问题的答案现在已更改 您好@amwinter:请提供代码(通过 git)/sn-p 从非安全页面进行安全调用 【参考方案1】:

您说您可以不使用 JavaScript 编写 SSL 协议……但我认为您的意思是您必须自己编写。

开源 Forge 项目提供了一个 JavaScript TLS 实现,以及一些用于处理跨域请求的 Flash:

http://github.com/digitalbazaar/forge/blob/master/README

查看自述文件末尾的博客文章,以更深入地了解其工作原理。

【讨论】:

【参考方案2】:

正如您所提到的,由于same origin policy,默认情况下这不起作用。现代浏览器正在实现CORS(跨源资源共享),您可以使用它来解决这个问题。但是,这只适用于 Internet Explorer 8+、Firefox 3.5+、Safari 4+ 和 Chrome,并且需要一些服务器端工作。您可能需要查看以下文章以进一步阅读此主题:

Cross-domain Ajax with Cross-Origin Resource Sharing Nicholas C. Zakas

您也可以将JSONP 用作Dan Beam suggested in another answer。它需要一些额外的 JavaScript 工作,并且您可能需要“填充”您的 Web 服务响应,但它是另一个适用于所有当前浏览器的选项。

【讨论】:

固体。很想看到旧版浏览器的解决方案,但这很干净并且在今天有效。 有一些针对旧浏览器的解决方案,使用反向代理,但您将失去 SSL 的好处...我想您不愿意牺牲这一点,因为在这种情况下您可以拥有通过 http(或两者)为您的 /ajaxservice/ 提供服务。 <script>src中使用https://不会失去好处... @Dan Beam:我猜这会弹出一些浏览器警告,不是吗?说您混合了安全和非安全内容? @amwinter:使用 easyXDM (easyxdm.net/wp) 即使在较旧的浏览器中,您也可以轻松完成这项工作——而且它比 CORS 更容易设置,因为它没有服务器端要求!在这里查看 ajax 示例 consumer.easyxdm.net/current/example/xhr.html 并在此处阅读更多信息 easyxdm.net/wp/2010/03/17/cross-domain-ajax【参考方案3】:

你不能用 XHR 绕过跨域来源(好吧,只有在 Firefox 3.5 中需要用户许可,这不是一个好的解决方案)。从技术上讲,从端口 80 (http) 移动到 443 (https) 违反了该策略(必须是相同的域和端口)。这是规范本身在此处提供的示例 - http://www.w3.org/Security/wiki/Same_Origin_Policy#General_Principles。

您是否研究过 JSONP (http://en.wikipedia.org/wiki/JSON#JSONP) 或 CSSHttpRequests (http://nb.io/hacks/csshttprequest)?

JSONP 是一种将<script> 标签添加到具有跨域预定义全局回调的页面的方法(因为您可以将<script>s src 放在网络上的任何位置)。示例:

<script>

    function globalCallback (a)  /* do stuff with a */ 

然后您将&lt;script&gt; 标签插入到您的其他域,如下所示:

    var jsonp = document.createElement('script');
    json.setAttribute('src','http://path.to/my/script');
    document.body.appendChild(jsonp);

</script>

并且在外部脚本的源代码中,您必须调用globalCallback 函数并使用您要传递给它的数据,如下所示:

 globalCallback("big":"phat":"object");

脚本执行后你会得到你想要的数据!

CSSHttpRequests 更像是一个 hack,所以我从来不需要使用它,不过如果你不喜欢 JSONP,请随意尝试一下,:)。

【讨论】:

好的,但是 big phat object 是在外部脚本中定义的。没有办法传入数据,是吗? 当您调用 globalCallback 时,它会将其传递给原始页面的函数...“pass[ing] in data” 将其返回到原始页面。我想将数据传递给远程脚本而不将其放入 url。 你没有把它放在 URL 中......你只是在调用一个全局函数。忽略此实例中标签的src。这就像您在 &lt;script&gt; 中声明了 function,然后在同一页面上的另一个 &lt;script&gt; 中调用它(因为您确实如此)。 哦,我明白你在说什么——你想将数据发送到你的远程脚本(而不是从中获取)。如果你希望它在功能上被隐藏,你可以将它存储在一个安全的 cookie 或 SSL 页面的 GET/POST 中(GET/POST 是加密的,就像我说过的那样)。

以上是关于来自非安全页面的安全 xmlhttprequest的主要内容,如果未能解决你的问题,请参考以下文章

浏览器原理 31 # 同源策略:为什么XMLHttpRequest不能跨域请求资源?

通过 Spring Security 和 CAS 登录后,如何在非安全 JSP 页面上显示登录用户详细信息?

混合内容问题 - 不安全的 XMLHttpRequest 端点

来自非安全服务器的HTTPS重定向在浏览器中显示错误消息

浏览器安全

Web 安全总结