为什么当从外部来源(如Excel,Word等等)点击链接时Cookie无法识别?

我注意到,当从Web浏览器(例如Excel或Word)从外部点击链接时,即使链接在相同浏览器窗口的新选项卡中打开,我的会话cookie最初也无法识别。

浏览器最终最终会识别它的cookie,但我为什么从Excel或Word的初始链接不起作用感到困惑。 为了使它更具挑战性,点击链接从Outlook工作正常。

有人知道为什么会发生这种情况吗? 我在PHP 5.3中使用Zend Framework。

这是因为MS Office使用Hlink.dll组件来查找链接是否是Office文档或其他东西。 MS Office希望打开文件链接的文件,而无需借助外部浏览器(使用IE6的Hlink.dll组件)。

如果会话cookie保护网站Hlink自然被redirect到login页面,并已达到HTML页面,并不能“理解”它打开它在外部浏览器。 请注意,它不会打开原始URL(预期行为),而是redirect的结果,即使它是302redirect。

微软在不支持的组件(Hlink.dll)中存在这个错误,而不是认识到它们把它交给我们的错误(试图让我们相信它是我们使用的SSO系统的缺陷,即会话cookie),并拒绝升级它。 它提供了closures MS Office 查找function的解决方法 :

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ Office\9.0\Common\Internet\ForceShellExecute:DWORD=1 

或者为我们解决服务器方面的问题,以避免HTTPredirect,并改变成Javascriptredirect或META REFRESHredirect(即让Hlink获取原始URL上的文本/ html页面并使其运行外部浏览器来处理它)。

我们遇到了同样的问题,写了一个开源的gem来帮助那些使用rails的人: https : //github.com/spilliton/fix_microsoft_links

您可以使用我们在任何框架上使用的相同方法:

  1. 检测用户代理是否来自Microsoft产品
  2. 使用元刷新标记呈现空白的html页面,这会导致浏览器使用正确的cookie刷新页面

代码示例: https : //github.com/spilliton/fix_microsoft_links/blob/master/lib/fix_microsoft_links.rb

修复VB.NET:

 Dim userAgent As String = System.Web.HttpContext.Current.Request.UserAgent If userAgent.Contains("Word") Or userAgent.Contains("Excel") Or userAgent.Contains("PowerPoint") Or userAgent.Contains("ms-office") Then System.Web.HttpContext.Current.Response.Clear() System.Web.HttpContext.Current.Response.Write("<html><head><meta http-equiv='refresh' content='0'/></head><body></body></html>") System.Web.HttpContext.Current.Response.End() End If 

它基本上强制浏览器刷新页面,所以请求来自浏览器的用户代理和所有正确的cookie。

以上是基于spilliton的答案的C#ASP.NET解决scheme。 在Global.asax.cs中,添加以下内容:

  private static string MSUserAgentsRegex = @"[^\w](Word|Excel|PowerPoint|ms-office)([^\w]|\z)"; protected void Application_OnPostAuthenticateRequest(object sender, EventArgs e) { if (System.Text.RegularExpressions.Regex.IsMatch(Request.UserAgent, MSUserAgentsRegex)) { Response.Write("<html><head><meta http-equiv='refresh' content='0'/></head><body></body></html>"); Response.End(); } } 

服务器端这在IIS中为我工作(使用重写规则)

 <rule name="WordBypass" enabled="true" stopProcessing="true"> <match url=".*" /> <conditions> <add input="{HTTP_USER_AGENT}" pattern="Word|Excel|PowerPoint|ms-office" /> </conditions> <action type="CustomResponse" statusCode="200" statusReason="Refresh" statusDescription="Refresh" /> </rule> 

PHP解决scheme:

这可以防止MS产品识别redirect。 MS因此从所需的链接启动浏览器。

 if (isset($_SERVER['HTTP_USER_AGENT'])) { $http_user_agent = $_SERVER['HTTP_USER_AGENT']; if (preg_match('/Word|Excel|PowerPoint|ms-office/i', $http_user_agent)) { // Prevent MS office products detecting the upcoming re-direct .. forces them to launch the browser to this link die(); } } 

此代码后redirect

这是我在WordPress的解决scheme。 将此添加到您的主题或另一个插件文件中的functions.php。

如果您的系统(如WP)将注销的用户发送到login页面并redirect到他们尝试访问的页面,这可能会有所帮助。 Word发送用户到这个页面,但是WP没有正确处理用户已经login的情况。这个代码检查是否有当前用户和redirect_to参数通过。 如果是,则redirect到redirect_to位置。

 function my_logged_in_redirect_to() { global $current_user; if($current_user->ID && $_REQUEST['redirect_to']) { wp_redirect($_REQUEST['redirect_to']); exit; } } add_action('wp', 'my_logged_in_redirect_to'); 

1.从excel / word指向http://example.com/from_excel.php

2.在“from_excel.php”redirect到您使用会话的页面

 <script>document.location.href = "http://example.com/page_with_session.php"; </script> 

这是Excel的VBA修复程序。 相同的概念可以应用于Microsoft Word。 基本上,不是从Excel内部引发链接,而是从一个shell中执行链接。 代码如下:

 Private Sub Worksheet_FollowHyperlink(ByVal objLink As Hyperlink) Application.EnableEvents = False Dim strAddress As String strAddress = "explorer " & objLink.TextToDisplay Dim dblReturn As Double dblReturn = Shell(strAddress) Application.EnableEvents = True End Sub 
  1. 对于包含链接的Excel工作表,请右键单击工作表选项卡并单击查看代码 。 VBA编辑器出现。
  2. 将代码粘贴到窗口中,然后closures编辑器。
  3. 修改页面中的每个链接,使其简单地指向它所在的单元格。为此:
  4. 用鼠标右键单击该链接,然后单击编辑超链接 。 出现编辑超链接窗口。
  5. 单击放置在此文档中
  6. 点击表格名称。
  7. input单元格引用 ,input单元格引用(例如A4)。
  8. 点击OK

几个注意事项:

  • 您将需要将电子表格保存为启用macros的电子表格(.xlsm)。 当用户打开电子表格时,会要求他们启用macros。 如果他们回答否,链接将不起作用。
  • 这些说明基于Excel 2010.大概以后的版本是相似的。

我不得不为ASP.NET网站解决这个问题,但我只想使用javascript / jQuery:

 var isCoBrowse = ('<%= Session["user"].ToString().ToLower() %>' != '0'); if (isCoBrowse && window.location.href.indexOf('ReturnUrl=') >= 0 && window.location.href.indexOf('dllCheq') == -1) { //redirect to the ReturnUrl & add dllCheq to the URI var toRedirect = decodeURIComponent(gup('ReturnUrl', window.location.href)) + '&dllCheq'; window.location = toRedirect; } 

我得到了gup函数: 如何从URL参数中获取值?

使用下面的微软给定链接提供的修补程序。 https://support.microsoft.com/en-us/kb/218153

我怀疑这是你如何设置cookie的问题。

由于networking创build的本质,example.com不被视为与www.example.com相同的域; 因此:您可以在www.example.com上login,而不是在example.comlogin。

换句话说,请检查您的word或excel文件中的URL – 是否与您在浏览器中login的域名相同?

有两个修复/解决scheme,这种cookie不一致:1.redirect谁试图加载您的网站没有www。 到www的同一页面。 (反之亦然),或者2.当您设置cookie时,请确保将域参数指定为“.example.com”。 最后一个点表示cookie也应该在该域的所有子域上有效。

我怀疑浏览器最终意识到这一点的原因,因为你最终可能最终login的URL与你login时的域名结构相同。

希望这可以帮助。