细节

细节

单击 Excel 中的超链接时,资源将被调用三次(如果之前访问过该 URL,则调用两次)。第一次和第二次被隐藏,第三次在浏览器中按预期进行。

细节

我在 Excel 2016 中使用超链接公式,如下所示,但在没有公式而只有超链接功能时也会出现问题:

=HYPERLINK(CONFIRM_NO_DATA_URL&B3)

无论如何,它应该调用这样的 URL

http://example.org/index.php?action=replyToEmailId&emailId=123123123

当我单击该单元格时,将打开一个带有正确 URL 的新选项卡。

但是:该 URL 实际上被调用了三次(我首先注意到了这一点,因为三封电子邮件在短暂延迟后发送)。

我试图通过将 Http-Headers 放入文件中来找出这个问题的来源。结果发现,excel 在浏览器中打开链接之前会在内部调用超链接。此外,提供的 Http-Headers 与最终请求不同。

第一个隐藏请求

这是使用 HEAD Http-Request-Method 的第一个请求:

{
    "HTTP_USER_AGENT": "Microsoft Office Excel 2014 (16.0.10730) Windows NT 10.0",
    "HTTP_X_OFFICE_MAJOR_VERSION": "16",
    "HTTP_X_MS_COOKIEURI_REQUESTED": "t",
    "HTTP_X_FEATUREVERSION": "1",
    "HTTP_ACCEPT_AUTH": "badger,Wlid1.1,Bearer",
    "REMOTE_PORT": "50216",
    "REQUEST_METHOD": "HEAD",
    "REQUEST_TIME_FLOAT": 1537284526.406,
    "REQUEST_TIME": 1537284526
}

HEAD 方法与 GET 相同,只是服务器不得在响应中返回消息正文。来源:[w3.org][1]

第二个隐藏请求

第二个请求有点难以识别,看起来 Excel 模拟了几个用户代理:

{
    "HTTP_ACCEPT": "*\/*",
    "HTTP_USER_AGENT": "Mozilla\/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident\/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; ms-office)",
    "HTTP_ACCEPT_ENCODING": "gzip, deflate",
    "REMOTE_PORT": "50221",
    "REQUEST_METHOD": "GET",
    "REQUEST_TIME_FLOAT": 1537284527.807,
    "REQUEST_TIME": 1537284527
}

问题

如何在 Excel 端防止这种行为?

(当然,我可以通过阻止包含“微软Office“或 REQUEST_METHOD”“,但我更喜欢一个干净的解决方案)。

补充说明

更新 #1

我刚刚发现这个所以-问题,这有点描述了相同的行为:https://stackoverflow.com/questions/24993813/link-in-excel-cause-duplicate-invocation

更新 #2 随着深入研究,我发现越来越多的所以-threads,像这样,对这个“功能”给出了很好的描述:https://webmasters.stackexchange.com/a/71151

不过,还是有一点区别的。我的第一个请求的 REQUEST METHOD 是 HEAD,而不是上面提到的答案中的 OPTION。无论如何,这仍然不能帮助我解决问题。

更新 #3 当我尝试重现这个问题时,我发现提出的请求不是两个而是三个。

答案1

我不确定,但在测试时,我注意到 Excel 正在“Internet Explorer”中打开链接以检查安全性或存在性。

例如,如果你输入了错误的 URL,Excel 会显示无法打开,表示出现了安全问题,而不是浏览器的问题。

我已经测试过了

=HYPERLINK("https://test.test")

并收到了此消息 错误信息

所以我不认为可以通过 excel “修复” 此类问题

答案2

这种行为(至少是第一个 HEAD 请求)是由所谓的Microsoft Office 协议发现引入 Office 2007请参阅 blogs.msdn.microsoft.com

HEAD 请求的目的是检查内容是否作为文档存在于 URL 位置,而不仅仅是作为只读会话中流下的临时资源

HEAD 方法与 GET 相同,只是服务器不得在响应中返回消息正文。来源:w3.org

根据此 technet 线程没有办法禁用此功能。

解决方法

由于没有办法真正禁用此功能,您只能在服务器端阻止请求(或使用客户端防火墙...):

PHP 中,可以使用以下几行代码拒绝此类请求。这只会捕获第一个隐藏请求的 REQUEST_METHOD,并再次检查第二个隐藏请求的奇怪用户代理:

    if ($_SERVER['REQUEST_METHOD'] == 'HEAD' OR 
        strpos($_SERVER['USER_AGENT'], 'ms-office') != NULL) {

        throw new Exception('This script may only be called directly');
        die();

    }

小心:这在上述场景中有效,请随意调整它以避免阻塞流量,这实际上是“想要的”。

进一步阅读

相关内容