JavaScript的window.location不会在请求头中设置referer。

35

我理解依赖请求头中的Referer不是正确的做法。但我的问题是,为什么如果我使用window.location,IE不会将Referer设置为请求头呢?有任何想法或修复方法吗?

这不会在请求头中设置Referer:

function load1() {
   window.location = "https://" + serverURL + "/path/folder/page.aspx";
}

<a href="javascript:load1()">Link 1</a>

虽然这样设定了:

<a href="https://hardcode.server.url/path/folder/page.aspx">Link 1</a>

你尝试过 go()、Navigate() 或 href 吗?window.location 不会导航到页面,而只是简单地重定向到那里。 - Anonymous
5个回答

39

根据您的帖子标题,您想使用JavaScript以编程方式更改当前页面,但仍然提供HTTP referrer(从我所理解的来看,使用<a>标签只是为了测试)。

您需要注意跨浏览器问题:

  • 当在以下浏览器中更改window.location.href时,将设置HTTP引用头(HTTP-Referer):
    • MSIE 9(但可能是任何版本高于9的版本)
    • Firefox(至少3.0、3.5、4.0、5.0,但最可能是所有版本)
    • Chrome(至少9,但最可能是所有版本)
    • Safari(至少5,但最可能是所有版本)
    • Opera(至少11,但最可能是所有版本)
  • MSIE(至少6、7、8):更改window.location.href时不会设置referrer(这就是为什么一些伪解决方案基于myLink.click()的原因)
  • Firefox(至少3.0、3.5、4.0):不存在click函数(这就是为什么基于myLink.click()的伪解决方案不起作用的原因)
  • Firefox 5:在Firefox 5下存在click函数,但不会更改窗口位置,因此所有依赖于myLink.click()方法的方法都将无法使用。调用myLink.onclick()myLink.onClick()会引发错误(“onclick不是函数”),因此基于这些调用的解决方案将无法使用。

为了处理这些跨浏览器问题,我正在使用以下方法:

function navigateToUrl(url) {
    var f = document.createElement("FORM");
    f.action = url;

    var indexQM = url.indexOf("?");
    if (indexQM>=0) {
        // the URL has parameters => convert them to hidden form inputs
        var params = url.substring(indexQM+1).split("&");
        for (var i=0; i<params.length; i++) {
            var keyValuePair = params[i].split("=");
            var input = document.createElement("INPUT");
            input.type="hidden";
            input.name  = keyValuePair[0];
            input.value = keyValuePair[1];
            f.appendChild(input);
        }
    }

    document.body.appendChild(f);
    f.submit();
}

navigateToUrl("http://foo.com/bar");

这种解决方案适用于上述所有浏览器类型和版本。它的优点是简单、多浏览器支持以及易于理解。

请注意,此解决方案尚未在HTTPS下测试。


2
这很好用,除非你想使用 method="GET" 并且在 URL 中有参数。 - six8
@Cixate:对于URL参数是true(我编辑了代码),但我不理解表单方法的参数,因为默认的表单方法是GET。 - Julien Kronegg
抱歉,我并不是在暗示您需要在标签中使用 method=GET,只是想说如果表单使用 GET 方法,就不能在 URL 中使用参数。但是您的隐藏参数解决方案很好。 - six8
这可能对所有人都很明显(除了我),但如果在页面加载之前运行此脚本,您将会得到一个 TypeError: document.body is null appendChild。因此,请在页面加载后再运行它 :) - TryHarder

26

设置 window.location 不等同于在页面上遵循链接。它会启动一个新的请求,就像用户在浏览器地址栏中输入了该URL。

我成功地找到了一个解决方法:

function goTo(url)
{
    var a = document.createElement("a");
    if(!a.click) //for IE
    {
         window.location = url;
         return;
    }
    a.setAttribute("href", url);
    a.style.display = "none";
    document.body.appendChild(a);
    a.click();
}

它在页面上创建一个链接并模拟点击。结果是更改 window.location 并填充引荐者信息。

http://ianso.blogspot.com/2006/01/referer-header-not-set-on-http.html


看到证据表明Firefox 5在执行a.click()时返回true,但不会导航到href。 - Kevin Hakanson
在运行于Windows 7上的Safari 5.0中,这会导致以下错误:TypeError: 'undefined' is not a function (evaluating 'a.click()') - Zorayr
@Zorayr:那是因为我把 a 传递给了 createElement 而不是 "a"。我已经纠正了代码。 - Evan Mulawski
我仍然在使用createElement('a')遇到相同的问题。有什么想法吗? - Zorayr
太好了!又是一个支持Internet Explorer的代码膨胀黑客。唯一真正的解决方案是将Internet Explorer从万维网上抹去。这里提到的黑客在我的情况下确实有效,但是Internet Explorer 8会显示一个安全警告,访问者必须接受,然后重新加载页面,才能正确地重定向到下载文件。 - undoIT
显示剩余3条评论

6

我没有足够的积分来评论Evan的答案以建议更正,所以我只能在这里发布更正。简而言之, document.createElement(a) 缺少引号,应该改为 document.createElement("a")。这应该也可以解决Kevin对FF5的担忧。

我编写的整个函数:

function goTo(url)
{
    var a = document.createElement("a");
    if (a.click)
    {
        // HTML5 browsers and IE support click() on <a>, early FF does not.
        a.setAttribute("href", url);
        a.style.display = "none";
        document.body.appendChild(a);
        a.click();
    } else {
        // Early FF can, however, use this usual method
        // where IE cannot with secure links.
        window.location = url;
    }
}

这在我们的HTTPS环境下可以在IE7、IE8、FF3、FF7和Chrome中运行。因此我想它也可以在FF5中运行。如果没有这个解决方法,在尝试设置window.location时,我们会在IE7和IE8中遇到403错误。关于Sha Le的问题为什么IE会这样做,我只能猜测他们认为这太不安全了。我在IE中也遇到了类似的window.open问题,不得不找到解决方法。


0

-4

没错,你的也可以用,但最终我做了:

<a href="#" id="linkOne">Link 1</a>

<script type="text/javascript">
   document.getElementById("linkOne").href = "https://" + serverURL + "/path/folder/page.aspx";
</script>

3
这只是设置超链接标签的href属性。除非用户点击该链接,否则不会发生任何事情。 - Evan Mulawski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接