代码之家  ›  专栏  ›  技术社区  ›  Jon Davis Glenn Block

在本地主机上运行时不执行JSONP回调

  •  11
  • Jon Davis Glenn Block  · 技术社区  · 15 年前

    这很奇怪,我想知道是否有人能解释为什么会这样。

    基本上,我一直在努力测试JSONP,以便实现其他站点可以使用的JSONWeb服务。我正在本地主机上进行开发——特别是Visual Studio 2008和Visual Studio 2008的内置Web服务器。

    因此,作为一个带有jquery的jsonp测试运行,我实现了以下功能:

    $().ready(function() {
      debugger;
      try {
        $.getJSON("<%= new Uri(Request.Url, "/").ToString() %>XssTest?callback=?", function(data) {
            alert(data.abc);
        });
      } catch (err) {
        alert(err);
      }
    });
    

    在服务器上……

    <%= Request["callback"] %>({abc : 'def'})
    

    因此,最终的结果是我在服务器上设置了一个断点,并且在客户端脚本和服务器上的第一个“调试器”语句上都得到了断点。在页面加载之后,实际上正在调用JSONP URL。这很管用。

    我遇到的问题是回调永远不会执行。我在IE8和火狐3.5中都测试过这个。没有人会调用回调。也从未到达catch(err)。什么都没发生!

    我在这个问题上已经坚持了一个星期,甚至在telnet上的指定端口上测试了一个手动键入的HTTP请求,以确保服务器正在返回格式…

    callbackfn({abc : 'def'})
    

    …就是这样。

    然后我突然意识到,如果我用一个全球化器(“.”)将主机名从localhost更改为localhost,那该怎么办,即 http://localhost.:41559/ 而不是 http://localhost:41559/ (是的,在任何主机名中添加一个点是合法的,对于DNS来说 global:: 是到c名称空间)。然后成功了!当我刚添加一个点时,InternetExplorer和Firefox3.5最终向我显示了一条警告消息。

    所以这让我想知道,这是怎么回事?为什么后期脚本标记的生成会使用Internet主机名而不是纯本地主机?或者这是正确的问题?

    显然,这是出于安全原因而实现的,但是他们试图保护什么??而且,通过让它与一个点一起工作,我是否只是在这个安全特性中暴露了一个安全漏洞?

    顺便说一句,我的hosts文件在为其他主机更改时,与localhost没有什么特别的关系;默认的127.0.0.1/::1仍然存在,下面没有覆盖。

    随访: 为了本地开发的目的,我增加了:

    127.0.0.1   local.mysite.com
    

    …到my hosts文件,然后将以下代码添加到my global.asax:

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        if (Request.Headers["Host"].Split(':')[0] == "localhost")
        {
            Response.Redirect(
                Request.Url.Scheme
                + "://"
                + "local.mysite.com"
                + ":" + Request.Url.Port.ToString()
                + Request.Url.PathAndQuery
                , true);
        }
    }
    
    2 回复  |  直到 15 年前
        1
  •  3
  •   jldupont    15 年前

    我要在那里给出一个答案;经过一番思考,我已经得出了自己的结论。

    这可能是一个安全特性,它的实现试图阻止Internet网站调用在客户机上运行的JSONP服务。

    一个网站只需浏览一个端口列表,并在不同的端口和路径上不断调用localhost。localhost'是少数几个动态DNS主机名之一,其含义取决于查询时间和位置,从而使潜在目标容易受到攻击。是的,将点(.)附加到“localhost”(“localhost”)会产生一个工作的变通方法,这确实暴露了一个安全漏洞,但确实为开发pupose提供了[暂时的]变通方法。

    一种更好的方法是将环回IP映射到主机文件中的新主机名条目,这样它就可以在本地工作,不容易被浏览器更新“修复”,而且除了在开发工作站之外,其他任何地方都不工作。

        2
  •  1
  •   Community noseratio    7 年前

    我也遇到了类似的问题。我尝试过的大多数解决方案都是IE(7),但我很难让火狐(3.5.2)玩球。

    我已经安装了httpfox,以查看如何在客户机上解释服务器的响应,我正在获取ns-error-dom-bad-uri。不过,我的情况与您的稍有不同,因为我正试图调用一个JSONP调用,使其返回宿主页面所在的同一个站点,然后这个调用将以302重定向到另一个站点的方式响应。(我使用重定向作为从返回到浏览器的两个域获取cookie的方便方法。)

    我正在使用jquery,最初我尝试通过$.ajax()执行标准的ajax调用。我认为,由于最初的请求和宿主页面位于同一个站点上,所以火狐只会按照302对另一个域的响应进行操作。但不,它似乎与XSS防御系统发生冲突。(注意,与 Returning redirect as response to XHR request 意味着jquery确实遵循302重定向标准datatype=“json”调用:重定向到同一个域很好;重定向到另一个域会在浏览器中生成ns-error-dom-bad-uri。)顺便说一句,我不明白为什么同一个域302重定向到其他域不能被遵循-毕竟,托管页的域就是启动重定向,为什么不能信任它?如果您担心脚本注入攻击,那么jsonp路由无论如何都会被滥用…

    jquery的$.getjson()带有?回调=?后缀在firefox中也会出现同样的错误。就像使用$.GetScript()滚动我自己的jsonp<script>标记一样。

    在HTML中有一个预先存在的脚本id=“jsonp”type=“text/javascript”></script>,然后使用$(“jsonp”).attr(“src”,url+”),这似乎起到了什么作用?callback=mycallback”)以调用jsonp调用。如果我这样做,那么将遵循跨域302重定向,并将JSON响应传递给mycallback(我在定义mycallback时将其与<script/>标记同时定义)。

    是的,我正在使用cassini和localhost开发所有这些功能: 港口 网址。Cassini不会响应非本地主机的URL,因此我无法轻松地尝试local.mysite.com,以查看这是否对我在上面尝试的解决方案有任何影响。然而,在本地主机的末尾粘贴一个点似乎已经解决了我所有的问题!

    现在我可以回到标准的$.Ajax(…)。数据类型:“jsonp”…})拨打本地主机 港口 而不是本地主机: 港口 一切都很好。我发现修改页面HTML中预先存在的脚本标记的src属性很有趣 允许调用普通的本地主机URL—我想按照您的思路,这可能是另一个安全漏洞。