Ho notato che quando si fa clic su un collegamento esternamente dal browser Web, ad esempio da Excel o Word, il cookie di sessione viene inizialmente non riconosciuto, anche se il collegamento si apre in una nuova scheda della stessa finestra del browser.
Il browser finisce per riconoscere il suo cookie, ma sono perplesso sul motivo per cui quel collegamento iniziale da Excel o Word non funziona. Per renderlo ancora più difficile, fare clic su un collegamento funziona bene da Outlook.
Qualcuno sa perché questo potrebbe accadere? Sto usando Zend Framework con PHP 5.3.
Questo perché MS Office utilizza il componente Hlink.dll per cercare se il collegamento è un documento di Office o altro. MS Office prevede di aprire il documento collegato all'interno dei documenti senza l'ausilio di browser esterni (utilizzando il componente Hlink.dll di IE6).
Se il cookie di sessione protegge il sito Web, Hlink viene naturalmente reindirizzato alla pagina di accesso e dopo aver raggiunto la pagina HTML e non è in grado di "capirlo" lo apre in un browser esterno. Si noti che non apre l'URL originale (comportamento previsto) ma il risultato del reindirizzamento, anche se era il reindirizzamento 302.
Microsoft ha quel bug nel componente non supportato (Hlink.dll), invece di riconoscere il bug che hanno consegnarlo alla nostra testa (cercando di convincerci che è un difetto del sistema SSO che usiamo, ovvero i cookie di sessione) e rifiuta per aggiornarlo. Offre soluzione che disattiva la funzionalità di ricerca di MS Office:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\
Office\9.0\Common\Internet\ForceShellExecute:DWORD=1
Oppure offrici a workaround serveride, per evitare reindirizzamenti HTTP e modifiche ai reindirizzamenti Javascript o ai reindirizzamenti META REFRESH (ad esempio per avere Hlink sulla pagina di testo/html sull'URL originale e farlo funzionare con un browser esterno per gestirlo).
Abbiamo avuto lo stesso problema e abbiamo scritto una gemma open source per aiutare chi utilizza Rails: https://github.com/spilliton/fix_Microsoft_links
Puoi usare lo stesso approccio che abbiamo usato su qualsiasi framework:
Esempio di codice qui: https://github.com/spilliton/fix_Microsoft_links/blob/master/lib/fix_Microsoft_links.rb
Lato server questo ha funzionato per me in IIS (usando una regola di riscrittura)
<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>
Ecco una soluzione per C # ASP.NET basata sulla risposta di spilliton sopra. In Global.asax.cs, aggiungere quanto segue:
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();
}
}
Correzione per 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
In pratica obbliga il browser ad aggiornare la pagina, quindi la richiesta arriva con l'agente utente del browser e tutti i cookie corretti.
Soluzione PHP:
Ciò impedisce al prodotto MS di riconoscere il reindirizzamento. MS quindi avvia un browser dal collegamento richiesto.
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();
}
}
.. reindirizzare dopo questo codice
1. Da Excel/Word punta a http://example.com/from_Excel.php
2.In "from_Excel.php" reindirizza alla pagina in cui si utilizza la sessione
<script>document.location.href = "http://example.com/page_with_session.php"; </script>
Ecco la mia soluzione per questo in WordPress. Aggiungi questo a functions.php nel tuo tema o in un altro file di plugin.
Ciò potrebbe essere utile se il tuo sistema, come WP, invia utenti disconnessi a una pagina di accesso con un reindirizzamento alla pagina a cui stavano tentando di accedere. Word inviava gli utenti a questa pagina, ma WP non gestiva correttamente il caso in cui un utente era già loggato. Questo codice controlla se c'è un utente corrente e un reindirizzamento al parametro passato. In tal caso, reindirizza al redirect_to posizione.
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');
Stiamo riscontrando un problema in cui due schede di Chrome sono aperte quando fai clic su un URL da MS Word e la pagina da aprire ha il reindirizzamento JavaScript: window.location.href=blabla
Effettuando il debug dal lato server, abbiamo confermato che ci sono richieste inviate dall'app Office, oltre a Chrome. Questo è così strano.
Tuttavia, controllando l'intestazione della richiesta "User-Agent" e restituendo una pagina vuota alle app di Office, il problema relativo alle schede DUE è stato risolto. Questa è sicuramente la cosa giusta da fare!
Ecco una correzione VBA, per Excel. Lo stesso concetto può essere applicato per Microsoft Word. Fondamentalmente, piuttosto che sparare il link da Excel, il codice esegue il collegamento all'interno di una shell . Ecco il codice:
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
Un paio di note:
Utilizzare la correzione fornita dal collegamento indicato di seguito. https://support.Microsoft.com/en-us/kb/218153
Ho dovuto risolvere questo problema per un sito ASP.NET ma volevo solo usare 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;
}
Ho ottenuto la funzione gup da: Come ottenere il valore dal parametro URL?
Non posso credere che chiamino questa funzionalità . Tuttavia, ecco un aggiornamento di funzione per 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]
Potrebbe non essere la migliore per quanto riguarda le prestazioni, dato che l'intera pagina viene inviata al posto di una risposta vuota, ma non volevo aggiungere altri moduli Apache solo per la correzione di una simile caratteristica di H ^ H ^ H ^ H.
Ecco un esempio della correzione che utilizza un middleware core 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);
}
}
Ecco come risolvere questo problema con Java e Spring tramite un filtro:
/**
* 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;
}
}