为了安全起见,获取JSONP请求来自的域名



我希望我的应用程序的用户能够在他们的网站上放置一些代码,并通过jsonp请求与我的服务器进行最少的交互。但是,我只希望远程请求能够来自我特别允许的远程站点。基本上,用户必须拥有我的应用程序的帐户。

为了安全起见,我的计划是:

  1. 要存储请求将来自的域允许在网站上放置代码
  2. 当服务器接收到远程请求时,它会获取域名并将其与数据库进行匹配
  3. 如果域匹配,则验证请求并返回数据等。如果它不同,我会认为它是一些XSS攻击对请求进行排序并拒绝,向远程返回一个错误

如何获取请求来自的域?为了在我的开发箱上进行测试,我建立了一个单独的静态网站,运行在不同的端口上

Server domain: localhost:8090
Remote domain: localhost:8095

使用getRemoteHost似乎返回127.0.0.1。在现实世界中,这会是远程域的ip吗?然后有可能从所述ip中找到人类可读的域名版本吗?根据ip存储和匹配可能不是一个好主意,因为我不知道试图连接到我的服务的远程站点是否由动态ip提供服务。。。

也许我在这里采取了错误的方法,所以如果我错了,请纠正我。无法向远程站点的用户请求用户名和密码,因为他们没有实际帐户。

也许更好的方法是将某种加密的令牌存储在数据库中,而不是域中,当我向用户提供要放置在其网站上的代码片段时,它可能包括一个隐藏的输入,其中包含该令牌的加密版本,该加密版本随每个请求传递?然而,在这种情况下,难道没有人能够通过查看页面源来复制隐藏的元素,并对服务器具有相同的访问权限吗?

一方面,你说"我只希望远程请求能够来自我特别允许的远程站点",但使用JSONP意味着你不会看到来自远程站点的请求——你会看到来自访问远程站点的浏览器的请求。这种区别是微妙但重要的,因为它严重限制了你的选择。

如果您想知道是哪个站点发起了JSONP请求,可以检查Referer标头。除了您不能依赖于它的设置,尤其是在HTTP/HTTPS转换中。然后你可能会想"嘿,我会使用CORS",但当然,任何人都可以创建一个带有任何标头的请求。我可以编写一个HTTP客户端,声称它是您的远程站点之一,并使用它们的凭据访问您的界面——所以,如果标头是限制访问的唯一方法,请知道它很容易被击败。

Referer头上的下一步是发布令牌并使用这些令牌进行识别。但是,正如您所指出的,远程站点必须将其提供给浏览器,浏览器才能创建请求。所以,有人可以复制它并在任何地方使用它。回到同一个问题。

您可以做的下一件事是发布令牌(用于标识)和共享密钥(用于授权)。然后,您可以要求远程站点使用共享机密来签署请求——说"是的,实际上是我,远程站点"。通过这种方式,远程站点为用户的浏览器提供签名,而不是秘密本身。您需要确保您签署的内容足以验证远程网站的意图(即网站希望用户浏览器执行的任何操作),并且应该包括时间戳以防止重播攻击。这需要从远程站点进行一些服务器端计算,但会阻止用户采取任何操作,除非远程站点明确允许。

然而。。。你提到这些远程站点上的用户没有帐户。如果这意味着它们对公众可用,那么任何人都可以获取其中一个远程网站,提取签名,并自己使用它来做远程网站用户可以做的事情。这不是实现的问题,而是架构的问题:你的设计需要随机的web浏览器来与你的服务交互,根本没有办法阻止中间人。使用共享的秘密可以让你有一定程度的控制,但你无法阻止它

在这一点上,我建议你退一步,考虑一下你真正想解决的问题。这个接口的作用是什么?这些远程网站上的浏览器需要直接与您连接吗?你想把谁挡在门外,为什么?如果他们绕过你的支票怎么办?

最新更新