J'ai remarqué que lorsqu'un cookie est cliqué en externe à partir du navigateur Web, tel que Excel ou Word, mon cookie de session est initialement non reconnu, même si le lien s'ouvre dans un nouvel onglet de la même fenêtre de navigateur.
Le navigateur finit par reconnaître son cookie, mais je ne comprends pas pourquoi ce lien initial d'Excel ou de Word ne fonctionne pas. Pour rendre la tâche encore plus difficile, cliquer sur un lien fonctionne bien à partir d'Outlook.
Est-ce que quelqu'un sait pourquoi cela pourrait se produire? J'utilise le Zend Framework avec PHP 5.3.
En effet, MS Office utilise le composant Hlink.dll pour rechercher si le lien est un document Office ou autre chose. MS Office s’attend à ouvrir le document lié dans les documents sans l’aide d’un navigateur externe (à l’aide du composant Hlink.dll de IE6).
Si le cookie de session protège le site Web, Hlink est naturellement redirigé vers la page de connexion et ayant atteint la page HTML sans pouvoir le "comprendre", il l'ouvre dans un navigateur externe. Notez qu'il n'ouvre pas l'URL d'origine (comportement attendu) mais le résultat de la redirection, même s'il s'agissait d'une redirection 302.
Microsoft a ce bogue dans le composant non pris en charge (Hlink.dll), au lieu de reconnaître le bogue, il le renvoie à notre tête (essayant de nous convaincre que c’est la faille du système SSO que nous utilisons, c’est-à-dire les cookies de session) et refuse pour le mettre à niveau. Il offre une solution de contournement qui désactive la fonctionnalité de recherche de MS Office:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\
Office\9.0\Common\Internet\ForceShellExecute:DWORD=1
Ou offrez-nous de contourner le problème côté serveur, afin d'éviter les redirections HTTP et de passer aux redirections Javascript ou META REFRESH (c'est-à-dire que Hlink obtienne la page text/html de l'URL d'origine et le fasse exécuter un navigateur externe pour le gérer).
Nous avons eu le même problème et avons écrit une gem open source pour aider les utilisateurs de Rails: https://github.com/spilliton/fix_Microsoft_links
Vous pouvez utiliser la même approche que nous avons utilisée sur n’importe quel framework:
Exemple de code ici: https://github.com/spilliton/fix_Microsoft_links/blob/master/lib/fix_Microsoft_links.rb
Côté serveur, cela fonctionnait pour moi dans IIS (à l'aide d'une règle de réécriture)
<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>
Voici une solution pour C # ASP.NET basée sur la réponse de spilliton ci-dessus. Dans Global.asax.cs, ajoutez les éléments suivants:
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();
}
}
Correction pour 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
Fondamentalement, il oblige le navigateur à actualiser la page. La demande est donc envoyée avec l'agent utilisateur du navigateur et tous les cookies appropriés.
Solution PHP:
Cela empêche le produit MS de reconnaître la redirection. MS lance donc un navigateur à partir du lien requis.
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();
}
}
.. rediriger après ce code
1.Dans Excel/Word, pointez sur http://example.com/from_Excel.php
2.Dans "from_Excel.php" redirige vers la page où vous utilisez la session
<script>document.location.href = "http://example.com/page_with_session.php"; </script>
Voici ma solution pour cela dans WordPress. Ajoutez ceci à functions.php dans votre thème ou dans un autre fichier plugin.
Cela peut être utile si votre système, tel que WP, envoie les utilisateurs déconnectés à une page de connexion avec une redirection vers la page à laquelle ils essayaient d'accéder. Word envoyait des utilisateurs à cette page, mais WP ne gérait pas correctement le cas où un utilisateur était déjà connecté. Ce code vérifie si un utilisateur actuel et un paramètre redirect_to sont passés. Si c'est le cas, il redirige vers l'emplacement 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');
Nous constatons un problème lorsque deux onglets Chrome sont ouverts lorsque vous cliquez sur une URL à partir de MS Word et que la page à ouvrir comporte une redirection JavaScript: window.location.href=blabla
En déboguant du côté des serveurs, nous avons confirmé qu'il y avait des demandes envoyées à partir de l'application Office, en plus de Chrome. C'est tellement bizarre.
Quoi qu'il en soit, en vérifiant l'en-tête de la requête "User-Agent" et en renvoyant une page vide aux applications Office, notre problème DEUX onglets a été résolu. C'est définitivement la bonne chose à faire!
Voici un correctif VBA pour Excel. Le même concept peut être appliqué à Microsoft Word. Fondamentalement, plutôt que de déclencher le lien à partir d'Excel, le code exécute le lien à partir d'un Shell . Voici le code:
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
Quelques notes:
Utilisez le correctif fourni par Microsoft avec le lien ci-dessous. https://support.Microsoft.com/en-us/kb/218153
Je devais résoudre ce problème pour un site ASP.NET mais je voulais seulement utiliser 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;
}
J'ai eu la fonction gup de: Comment obtenir la valeur du paramètre d'URL?
Je ne peux pas croire qu'ils appellent cela une fonctionnalité . Cependant, voici une fonctionnalité pour 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]
Les performances ne seraient peut-être pas optimales, car toute la page était envoyée au lieu d'une réponse vide, mais je ne voulais pas ajouter un autre module Apache uniquement pour corriger une telle fonctionnalité.
Voici un exemple de solution utilisant un middleware de base 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);
}
}
Voici comment résoudre ce problème avec Java et Spring via un filtre:
/**
* 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;
}
}