我注意到,当从网络浏览器(例如从Excel或Word)在外部单击链接时,即使该链接在同一浏览器窗口的新选项卡中打开,最初也无法识别我的会话cookie。
浏览器最终最终识别出它的cookie,但是我对为什么Excel或Word的初始链接不起作用感到困惑。为了使它更具挑战性,单击链接可以在Outlook中正常工作。
有人知道为什么会这样吗?我正在使用Zend Framework和PHP 5.3。
我注意到,当从网络浏览器(例如从Excel或Word)在外部单击链接时,即使该链接在同一浏览器窗口的新选项卡中打开,最初也无法识别我的会话cookie。
浏览器最终最终识别出它的cookie,但是我对为什么Excel或Word的初始链接不起作用感到困惑。为了使它更具挑战性,单击链接可以在Outlook中正常工作。
有人知道为什么会这样吗?我正在使用Zend Framework和PHP 5.3。
Answers:
这是因为如果链接是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页面,并使其运行外部浏览器进行处理)。
HKLM\SOFTWARE\Wow6432Node\Microsoft\Office\9.0\Common\Internet\
,是的,它仍然9.0
适用于MS Office 2013
wow6432node
如果使用32位Office,则唯一的更改如上所述。
我们遇到了同样的问题,并编写了一个开源gem来帮助那些使用rails的人:https : //github.com/spilliton/fix_microsoft_links
但是,您可以使用在任何框架上使用的相同方法:
此处的示例代码:https : //github.com/spilliton/fix_microsoft_links/blob/master/lib/fix_microsoft_links.rb
服务器端在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>
修复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一起出现。
这是基于上述溢出答案的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();
}
}
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();
}
}
..在此代码后重定向
1.从excel / word指向http://example.com/from_excel.php
2.在“ from_excel.php”中重定向到您使用会话的页面
<script>document.location.href = "http://example.com/page_with_session.php"; </script>
以下是通过过滤器使用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;
}
}
这是使用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);
}
}
这是我在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');
这是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
一些注意事项:
我简直不敢相信他们称其为功能。但是,这是针对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功能。
我必须为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参数获取值?
使用下面的Microsoft给定链接提供的修复程序。https://support.microsoft.com/zh-CN/kb/218153
我怀疑这与您如何设置Cookie有关。
由于网络创建方式的性质,example.com与www.example.com
;因此:您可以在登录,www.example.com
而不能在登录example.com
。
因此,换句话说,检查您的word或excel文件中的URL-它是与您在浏览器中登录的域相同的域吗?
Cookie不一致的解决方法有两种:1.重定向试图在没有www的情况下加载您网站的任何人。与www到同一页面。(反之亦然),或2.在设置Cookie时,请确保将域参数指定为“ .example.com”。前导点表示Cookie也应在该域的所有子域上均有效。
我怀疑浏览器最终识别出它的原因是,您最终可能最终登陆了具有与您登录方式相同的域结构的URL。
希望这可以帮助。