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


73

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

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

有人知道为什么会这样吗?我正在使用Zend Framework和PHP 5.3。


2
我认为这个问题与框架,会话甚至PHP都没有关系。但是更多的浏览器相关。您使用什么浏览器,是否尝试过其他浏览器?它发送任何cookie吗?
您的常识2010年

1
这发生在IE8,Chrome和Firefox中。在调试时,似乎没有发送cookie或正在创建新的cookie-我无法确认。但是我确信没有发送正确的cookie。
尼克

Answers:


87

这是因为如果链接是Office文档或其他内容,MS Office将使用Hlink.dll组件进行查找。MS Office希望在不借助外部浏览器的情况下打开文档中链接的文档(使用IE6的Hlink.dll组件)。

如果会话cookie保护网站,则Hlink自然会被重定向到登录页面并到达HTML页面并且无法“理解”,它将在外部浏览器中将其打开。请注意,它打开的不是原始URL(预期的行为),而是打开重定向的结果,即使它是302重定向也是如此。

微软在不受支持的组件(Hlink.dll)中存在该bug,而不是将它们转移到我们的头上(他们试图使我们确信这是我们使用的SSO系统的缺陷,即会话cookie),而不是将其移交给我们,并拒绝对其进行升级。它提供了解决方法,可以关闭MS Office的查找功能

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

或让我们在服务器端变通,以避免HTTP重定向并更改为Javascript重定向或META REFRESH重定向(即让Hlink在原始URL上获取text / html页面,并使其运行外部浏览器进行处理)。


谢谢你 我已经完全被这种行为所困扰。每个其他Office应用程序都可以让我们粘贴到我们应用程序的链接没有问题,但是MS Office每次都会获得登录页面。
肖恩

1
谢谢,它帮助了我!您在此处有链接,但是我仍然会输入此链接。对于64位Windows版本上的32位Office版本,密钥是HKLM\SOFTWARE\Wow6432Node\Microsoft\Office\9.0\Common\Internet\ ,是的,它仍然9.0适用于MS Office 2013
244年

12
他们试图将其归咎于SSO是多么邪恶。
dougd_in_nc

2
有人可以为最新的Microsoft Office更新它吗?
Boris D. Teoharov

9.0注册表路径适用于所有版本的Office。wow6432node如果使用32位Office,则唯一的更改如上所述。
阿米特·奈杜

19

我们遇到了同样的问题,并编写了一个开源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


这个宝石是一个很好的解决方案。
mastaBlasta 2013年

伙计,非常感谢您。我用了你的代码来构建一个中间件express.js github.com/auth0/fix-office-link
何塞F. Romaniello

没问题!很高兴它被证明是有用的:)
溢出2014年

17

服务器端在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>

2
对于我的MVC5应用程序,这是快速简便的修复程序。我根据需要自定义了模式。请注意,这需要在Web服务器上安装Microsoft Url Rewrite软件。iis.net/downloads/microsoft/url-rewrite
laylarenee

在IIS中,比应用程序本身

在我的ASP.Net 4.5 Web表单应用程序上,这就像一个魅力。万分感谢!@Martin
Nitesh

我将代码放在应用程序的web.config文件中,并且效果很好。
开发人员

6

修复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一起出现。


6

这是基于上述溢出答案的C#ASP.NET解决方案。在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();
        }
    }

2
我还会在检查正则表达式之前添加一个检查请求是否已通过身份验证的检查。在每个请求上将userAgent与正则表达式进行匹配都会导致性能问题。
Trailmax 2015年

6

PHP解决方案:

这将阻止MS产品识别重定向。因此,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();
    }
}

..在此代码后重定向



2

以下是通过过滤器使用Java和Spring的解决方法:

/**
 * To see why this is necessary, check out this page:
 * https://support.microsoft.com/en-gb/help/899927.
 */
public class MicrosoftFilter extends OncePerRequestFilter {
  @Override
  protected void doFilterInternal(final HttpServletRequest request,
      final HttpServletResponse response,
      final FilterChain filterChain) throws ServletException, IOException {
    //Serve up a blank page to anything with a Microsoft Office user agent, forcing it to open the
    //URL in a browser instead of trying to pre-fetch it, getting redirected to SSO, and losing
    //the path of the original link.
    if (!request.getHeader("User-Agent").contains("ms-office")) {
      filterChain.doFilter(request, response);
    }
  }
}

/**
 * Security configuration.
 */
@Configuration
public class SecurityConfiguration {
  @Bean
  public FilterRegistrationBean microsoftFilterRegistrationBean() {
    FilterRegistrationBean<MicrosoftFilter> registrationBean = new FilterRegistrationBean<>();
    registrationBean.setFilter(new MicrosoftFilter());
    registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return registrationBean;
  }
}

1
首先,我简直不敢相信我什至发现了这个问题……很高兴为如此众多的平台提供了解决方案……但是Java是我所需要的解决方案……谢谢大家!
溅出

2

我们看到一个问题,当单击MS Word中的URL时会打开两个Chrome标签,并且打开的页面具有JavaScript重定向: window.location.href=blabla

通过服务器端的调试,我们确认除了Chrome之外,还有其他Office应用发送的请求。太奇怪了

但是无论如何,通过检查请求标头“ User-Agent”,并将空白页返回到Office应用程序,我们的两个选项卡问题得到了解决。这绝对是正确的事情!


您从Office应用程序中看到什么User-Agent?
pbarney

2

这是使用dotnet核心中间件的修复程序示例:

public class MicrosoftOfficeLinksHandlingMiddleware
{
    private static readonly Regex MsUserAgentsRegex = new Regex(@"[^\w](Word|Excel|PowerPoint|ms-office)([^\w]|\z)");
    private readonly RequestDelegate _next;

    public MicrosoftOfficeLinksHandlingMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        string userAgent = context.Request.Headers["User-Agent"].FirstOrDefault();

        if (userAgent != null && MsUserAgentsRegex.IsMatch(userAgent))
        {
            // just return an empty response to the office agent
            return;
        }

        await _next(context);
    }
}

1

这是我在WordPress中的解决方案。将其添加到主题或其他插件文件中的functions.php中。

如果您的系统(例如WP)将注销的用户发送到登录页面,并重定向到他们尝试访问的页面,则这可能会有所帮助。Word正在将用户发送到此页面,但是WP无法正确处理用户已经登录的情况。此代码检查是否有当前用户并传递了redirect_to参数。如果是这样,它将重定向到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的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. 将代码粘贴到窗口中,然后关闭编辑器。
  3. 修改页面中的每个链接,使其仅指向其所在的单元格。为此:
  4. 右键单击该链接,然后单击“编辑超链接”。出现“编辑超链接”窗口。
  5. 单击放置在此文档中
  6. 单击工作表名称。
  7. 对于键入单元格引用,输入单元格引用(例如A4)。
  8. 单击确定

一些注意事项:

  • 您将需要将电子表格另存为启用宏的电子表格(.xlsm)。用户打开电子表格时,将要求他们启用宏。如果他们回答“否”,则链接将不起作用。
  • 这些说明基于Excel2010。大概更高的版本是相似的。

大概在OS X上,这将需要使用“ open”而不是“ explorer” ...或者这种方法甚至可以在Mac上使用?
guymac

1

我简直不敢相信他们称其为功能。但是,这是针对Apache的功能修复:

RewriteEngine On

# Send a 200 to MS Office so it just hands over control to the browser
# It does not use existing session cookies and would be redirected to the login page otherwise
# https://www.wimpyprogrammer.com/microsoft-office-link-pre-fetching-and-single-sign-on/

RewriteCond %{HTTP_USER_AGENT} ;\sms-office(\)|;)
RewriteRule .* - [R=200,L]

可能不是最好的性能,因为整个页面都被发送而不是一个空的响应,但是我不想添加另一个Apache模块只是为了修复这种idio ^ H ^ H ^ H ^ H功能。


1

NGINX解决方案如下:

if ($http_user_agent ~* Word|Excel|PowerPoint|ms-office) {
    return 200 '<html><head><meta http-equiv="refresh" content="0"/></head><body></body></html>';
}

您可以将其放在serverlocation块中。像魅力一样工作。


0

我必须为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参数获取值?



-2

我怀疑这与您如何设置Cookie有关。

由于网络创建方式的性质,example.com与www.example.com;因此:您可以在登录,www.example.com而不能在登录example.com

因此,换句话说,检查您的word或excel文件中的URL-它是与您在浏览器中登录的域相同的域吗?

Cookie不一致的解决方法有两种:1.重定向试图在没有www的情况下加载您网站的任何人。与www到同一页面。(反之亦然),或2.在设置Cookie时,请确保将域参数指定为“ .example.com”。前导点表示Cookie也应在该域的所有子域上均有效。

我怀疑浏览器最终识别出它的原因是,您最终可能最终登陆了具有与您登录方式相同的域结构的URL。

希望这可以帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.