Warum werden Cookies nicht erkannt, wenn auf einen Link von einer externen Quelle (z. B. Excel, Word usw.) geklickt wird?

73

Ich habe festgestellt, dass beim externen Klicken auf einen Link über den Webbrowser, z. B. aus Excel oder Word, mein Sitzungscookie zunächst nicht erkannt wird, selbst wenn der Link in einem neuen Tab desselben Browserfensters geöffnet wird.

Der Browser erkennt schließlich sein Cookie, aber ich bin verwirrt, warum dieser erste Link aus Excel oder Word nicht funktioniert. Um es noch schwieriger zu machen, funktioniert das Klicken auf einen Link in Outlook einwandfrei.

Weiß jemand, warum dies passieren könnte? Ich verwende das Zend Framework mit PHP 5.3.

Nick
quelle
2
Ich denke, diese Frage hat keinen Bezug zu Frameworks oder Sessions und sogar zu PHP. Aber mehr browserbezogen. Welchen Browser verwenden Sie und haben Sie einen anderen ausprobiert? Sendet es einen Cookie?
Ihr gesunder Menschenverstand
1
Dies geschieht in IE8, Chrome und ich glaube Firefox. Beim Debuggen stellte sich heraus, dass entweder kein Cookie gesendet oder ein neues erstellt wurde - ich konnte es nicht bestätigen. Aber ich bin sicher, dass der richtige Cookie nicht gesendet wurde.
Nick

Antworten:

87

Dies liegt daran, dass MS Office die Komponente Hlink.dll verwendet, um zu prüfen, ob es sich bei dem Link um ein Office-Dokument oder etwas anderes handelt. MS Office erwartet, dass das in Dokumenten verknüpfte Dokument ohne die Hilfe eines externen Browsers geöffnet wird (mithilfe der Hlink.dll-Komponente von IE6).

Wenn ein Sitzungscookie die Website schützt, wird Hlink natürlich zur Anmeldeseite umgeleitet und hat die HTML-Seite erreicht und kann sie nicht "verstehen". Sie öffnet sie in einem externen Browser. Beachten Sie, dass nicht die ursprüngliche URL (erwartetes Verhalten) geöffnet wird, sondern das Ergebnis der Umleitung, selbst wenn es sich um eine 302-Umleitung handelte.

Microsoft hat diesen Fehler in einer nicht unterstützten Komponente (Hlink.dll), anstatt den Fehler zu erkennen, den sie uns übergeben (um uns davon zu überzeugen, dass es sich um einen Fehler des von uns verwendeten SSO-Systems handelt, dh um Sitzungscookies), und weigert sich, ihn zu aktualisieren. Es bietet eine Problemumgehung, mit der die Suchfunktion von MS Office deaktiviert wird :

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

Oder bieten Sie uns an, die Server-Seite zu umgehen, um HTTP-Weiterleitungen zu vermeiden und in Javascript-Weiterleitungen oder META REFRESH-Weiterleitungen zu wechseln (dh, Hlink muss eine Text- / HTML-Seite auf die ursprüngliche URL übertragen und einen externen Browser ausführen, um damit umzugehen).

myroslav
quelle
Danke dafür. Dieses Verhalten hat mich völlig verblüfft. Mit jeder anderen Office-Anwendung können wir problemlos Links zu unserer App einfügen, aber MS Office erhält jedes Mal die Anmeldeseite.
Sean
1
Danke, es hat mir geholfen! Sie haben den Link dort, aber ich werde ihn trotzdem eingeben. Für eine 32-Bit-Version von Office unter 64-Bit-Version von Windows ist der Schlüssel HKLM\SOFTWARE\Wow6432Node\Microsoft\Office\9.0\Common\Internet\ , und ja, es ist immer noch 9.0auch für MS Office 2013
244an
12
Wie böse von ihnen, die SSO dafür verantwortlich zu machen.
Dougd_in_nc
2
Kann jemand dies für das neueste Microsoft Office aktualisieren?
Boris D. Teoharov
Dieser Registrierungspfad 9.0 gilt für alle Versionen von Office. Die einzige Änderung ist wow6432nodewie oben angegeben, wenn Sie 32-Bit-Office verwenden.
Amit Naidu
19

Wir hatten das gleiche Problem und haben ein Open-Source-Juwel geschrieben, um denjenigen zu helfen, die Rails verwenden: https://github.com/spilliton/fix_microsoft_links

Sie können jedoch denselben Ansatz verwenden, den wir für jedes Framework verwendet haben:

  1. Ermitteln Sie, ob der Benutzeragent von einem Microsoft-Produkt stammt
  2. Rendern Sie eine leere HTML-Seite mit einem Meta-Refresh-Tag, wodurch der Browser die Seite mit den richtigen Cookies aktualisiert

Beispielcode hier: https://github.com/spilliton/fix_microsoft_links/blob/master/lib/fix_microsoft_links.rb

Spilliton
quelle
Dieses Juwel ist eine großartige Lösung.
MastaBlasta
Mann, vielen Dank dafür. Ich verwendete Code eine Middleware zu bauen für Express.js github.com/auth0/fix-office-link
José F. Romaniello
Kein Problem!
Ich bin
17

Serverseitig funktionierte dies für mich in IIS (unter Verwendung einer Umschreiberegel)

<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>
Martin Lee
quelle
2
Dies war eine schnelle und einfache Lösung für meine MVC5-App. Ich habe das Muster nach Bedarf angepasst. Beachten Sie, dass hierfür die Microsoft Url Rewrite-Software auf dem Webserver installiert sein muss. iis.net/downloads/microsoft/url-rewrite
Laylarenee
Besser in IIS, um dieses Verhalten zu korrigieren als in der App selbst
Dan
Dies funktionierte wie ein Zauber in meinen ASP.Net 4.5-Webformularanwendungen. Danke vielmals! @ Martin
Nitesh
Ich habe den Code in die Datei web.config der Anwendung eingefügt, und er funktioniert hervorragend.
Entwickler
6

Fix für 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

Grundsätzlich wird der Browser gezwungen, die Seite zu aktualisieren, sodass die Anfrage beim Benutzeragenten des Browsers und allen korrekten Cookies eingeht.

Fiona - myaccessible.website
quelle
6

Hier ist eine Lösung für C # ASP.NET basierend auf der obigen Antwort von spilliton. Fügen Sie in Global.asax.cs Folgendes hinzu:

    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();
        }
    }
Mike
quelle
2
Ich würde auch eine Prüfung hinzufügen, ob die Anfrage authentifiziert ist, bevor nach Regex gesucht wird. Das Abgleichen eines userAgent mit einem regulären Ausdruck bei jeder Anforderung kann zu Leistungsproblemen führen.
Trailmax
6

PHP-Lösung:

Dies verhindert, dass das MS-Produkt die Weiterleitung erkennt. MS startet daher einen Browser über den erforderlichen Link.

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();
    }
}

.. nach diesem Code umleiten

Tim Smith
quelle
2

1.Von Excel / Word-Punkt auf http://example.com/from_excel.php

2.In "from_excel.php" leiten Sie zu der Seite weiter, auf der Sie die Sitzung verwenden

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

So umgehen Sie dies mit Java und Spring über einen Filter:

/**
 * 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;
  }
}
Rupert Madden-Abbott
quelle
1
Erstens kann ich nicht glauben, dass ich diese Frage überhaupt gefunden habe ... schön, dass es Lösungen für so viele Plattformen gibt ... aber Java ist die, die ich brauchte ... Vielen Dank an alle!
Splashout
2

Wir sehen ein Problem, dass ZWEI Chrome-Registerkarten geöffnet werden, wenn Sie auf eine URL aus MS Word klicken, und die zu öffnende Seite über eine JavaScript-Umleitung verfügt: window.location.href=blabla

Durch das Debuggen von der Serverseite haben wir bestätigt, dass neben Chrome auch Anforderungen von der Office-App gesendet werden. Das ist so komisch.

Durch Überprüfen des Anforderungsheaders "User-Agent" und Zurückgeben einer leeren Seite an Office-Apps wurde das Problem mit den beiden Registerkarten behoben. Das ist definitiv das Richtige!

hailong
quelle
Welchen User-Agent sehen Sie in Office-Apps?
Pbarney
2

Hier ist ein Beispiel für das Update mit einer Dotnet-Core-Middleware:

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);
    }
}
Konstantin Volynskiy
quelle
1

Hier ist meine Lösung dafür in WordPress. Fügen Sie dies zu functions.php in Ihrem Theme oder einer anderen Plugin-Datei hinzu.

Dies kann hilfreich sein, wenn Ihr System wie WP abgemeldete Benutzer an eine Anmeldeseite mit einer Umleitung zu der Seite sendet, auf die sie zugreifen wollten. Word hat Benutzer auf diese Seite gesendet, aber dann hat WP den Fall, in dem ein Benutzer bereits angemeldet war, nicht richtig behandelt. Dieser Code prüft, ob ein aktueller Benutzer und ein Parameter redirect_to übergeben wurden. In diesem Fall wird an den Speicherort redirect_to weitergeleitet.

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');
strangerstudios
quelle
1

Hier ist ein VBA-Fix für Excel. Das gleiche Konzept kann für Microsoft Word angewendet werden. Anstatt den Link in Excel auszulösen, führt der Code den Link im Grunde genommen in einer Shell aus. Hier ist der 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
  1. Klicken Sie für die Excel-Tabelle, die die Links enthält, mit der rechten Maustaste auf die Registerkarte Blatt und klicken Sie auf Code anzeigen . Der VBA-Editor wird angezeigt.
  2. Fügen Sie den Code in das Fenster ein und schließen Sie den Editor.
  3. Ändern Sie jeden Link auf der Seite so, dass er einfach auf die Zelle verweist, in der er sich befindet. Gehen Sie dazu folgendermaßen vor:
  4. Klicken Sie mit der rechten Maustaste auf den Link, und klicken Sie auf Hyperlink bearbeiten . Ein Fenster zum Bearbeiten von Hyperlinks wird angezeigt.
  5. Klicken Sie auf In dieses Dokument einfügen .
  6. Klicken Sie auf den Blattnamen.
  7. Geben Sie unter Typ der Zellreferenz eine Zellreferenz ein (z. B. A4).
  8. Klicken Sie auf OK .

Ein paar Anmerkungen:

  • Sie müssen die Tabelle als makrofähige Tabelle (.xlsm) speichern. Wenn Benutzer die Tabelle öffnen, werden sie aufgefordert, Makros zu aktivieren. Wenn sie mit Nein antworten, funktionieren die Links nicht.
  • Diese Anweisungen basieren auf Excel 2010. Vermutlich sind spätere Versionen ähnlich.
Squidx3
quelle
Vermutlich müsste dies unter OS X "open" anstelle von "explorer" verwenden ... oder würde diese Methode sogar auf einem Mac funktionieren?
Guymac
1

Ich kann nicht glauben, dass sie dies eine Funktion nennen. Hier ist jedoch ein Featurefix für 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]

In Bezug auf die Leistung ist dies möglicherweise nicht die beste Leistung, da die gesamte Seite anstelle einer leeren Antwort gesendet wird, aber ich wollte keine weiteren Apache-Module hinzufügen, nur um eine solche idio ^ H ^ H ^ H ^ H-Funktion zu beheben.

tbart
quelle
1

NGINX-Lösung unten:

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

Sie können es in den serveroder locationBlock setzen. Funktioniert wie Charme.

Tomek
quelle
0

Ich musste dieses Problem für eine ASP.NET-Site lösen, wollte aber nur Javascript / jQuery verwenden:

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;
}

Ich habe die gup-Funktion erhalten von: Wie erhalte ich den Wert aus dem URL-Parameter?

RIanGillis
quelle
0

Verwenden Sie den von Microsoft bereitgestellten Fix unter dem folgenden Link. https://support.microsoft.com/en-us/kb/218153

Tushar Patel
quelle
1
Dieser Link wurde bereits in der akzeptierten Antwort erwähnt. Darüber hinaus hat die hier vorgeschlagene Lösung dramatische Auswirkungen auf die Verknüpfung der Funktionen aller Office-Produkte.
kmote
-2

Ich vermute, dies hängt davon ab, wie Sie die Cookies setzen.

Aufgrund der Art und Weise, wie das Web erstellt wurde, wird example.com nicht als dieselbe Domain angesehen wie www.example.com; daher: Sie können bei angemeldet www.example.comund nicht angemeldet sein bei example.com.

Mit anderen Worten, überprüfen Sie die URL in Ihrer Word- oder Excel-Datei. Entspricht dies der Domain, mit der Sie in Ihrem Browser angemeldet sind?

Es gibt zwei Korrekturen / Lösungen für diese Cookie-Inkonsistenz: 1. Leiten Sie jeden weiter, der versucht, Ihre Site ohne das WWW zu laden. auf die gleiche Seite mit dem www. (oder umgekehrt) oder 2. Wenn Sie das Cookie setzen, stellen Sie sicher, dass Sie das Domain-Argument als ".example.com" angeben. Der führende Punkt gibt an, dass das Cookie auch für alle Subdomains dieser Domain gültig sein sollte.

Ich vermute, der Grund, warum der Browser dies irgendwann erkennt, liegt darin, dass Sie wahrscheinlich auf einer URL landen, die dieselbe Domain-Struktur aufweist wie Sie.

Hoffe das hilft.

Lev
quelle