Sitzungen & Sicherheit

Dokumentensitzungen und Zugriffskontrolle

Ein Doconut‑Token identifiziert ein geöffnetes Dokument. Wenn irgendeine Anfrage, die ihn trägt, bedient würde, könnte derjenige, der ihn erhalten hat, jede Seite lesen. Diese Seite erklärt, was eine Dokumentensitzung enthält, wie lange sie lebt und wie DocImage.axd entscheidet, wer ihre Seiten sehen darf – auf einem Server und in einem Web‑Farm.

Was eine Dokumentensitzung enthält

Jeder erfolgreiche OpenDocumentAsync erzeugt eine Sitzung, die im Speicher gehalten wird:

  • der geladene Format‑Viewer — die Engine‑Instanz, die das geparste Dokument hält,
  • seitenbezogener Zustand — Drehungen, Spiegelungen und die Annotationsdaten, die der Benutzer im Widget anwendet,
  • der optionale Suchindex, erstellt bei der ersten Suche (oder geladen aus einer vorgefertigten .srh‑Datei),
  • das Sitzungs‑Wasserzeichen von DocOptions.Watermark.

Lebensdauer

Sitzungen verfallen nach einem gleitenden Fenster: DocOptions.TimeOut Minuten (Standard 60), zurückgesetzt durch jede Anfrage, die das Token präsentiert. Wenn eine Sitzung endet – durch Ablauf oder durch CloseDocument(token) – wird ihre Dokumenten‑Engine freigegeben und ihr Speicher sofort freigegeben.

csharp
// Eine kurzlebige Sitzung für eine einmalige Vorschau
var token = await viewer.OpenDocumentAsync(path, new DocOptions { TimeOut = 10 });

Eine Anfrage mit einem abgelaufenen Token erhält ein Fehlermotiv mit dem Text Document session not found. Please re-open document.. Die Seite muss das Dokument erneut öffnen, um ein neues Token zu erhalten. Auf einem einzelnen Server beendet das Recyceln des Anwendungspools ebenfalls jede Sitzung.

Seiten werden nur der Sitzung bereitgestellt, die sie geöffnet hat

Mit UnsafeMode = false – dem Standard – gewährt das Öffnen eines Dokuments Zugriff auf die ASP.NET‑Sitzung der Anfrage, die es geöffnet hat, indem ein secure-{token}‑Eintrag in diese Sitzung geschrieben wird. DocImage.axd erfordert selbst Sitzungszustand und liefert eine Seite nur, wenn die anfragende Sitzung diesen Eintrag enthält. Jeder andere Browser, der dasselbe Token präsentiert, erhält ein Fehlermotiv mit dem Text You Are Not Authorized To View This Page.

csharp
Doconut.DoconutHost.Initialize(options =>
{
    // false (der Standard): DocImage.axd liefert eine Seite nur an die ASP.NET‑Sitzung, die sie geöffnet hat
    // das Dokument. Der Handler fordert den Sitzungsstatus selbst an; er benötigt nur, dass die Site nicht
    // den Sitzungsstatus in Web.config ausschalten.
    options.UnsafeMode = false;
});

Drei praktische Konsequenzen:

  • Der Öffnungs‑Endpunkt benötigt Sitzungszustand. MVC‑Controller und Web‑Forms‑Seiten haben ihn standardmäßig. Ein benutzerdefinierter IHttpHandler hat ihn nicht, es sei denn, er implementiert System.Web.SessionState.IRequiresSessionState. Ein Öffnen, das ohne Sitzung läuft, hat nichts zu gewähren, sodass der Viewer auf jeder Seite „You Are Not Authorized To View This Page.“ anzeigt.
  • Sitzungszustand muss aktiviert bleiben. <sessionState mode="Off" /> in Web.config deaktiviert sowohl die Gewährung als auch die Prüfung, und jede Seite wird abgelehnt.
  • Der Browser muss das Sitzungs‑Cookie senden. Die Anfragen des Widgets sind Same‑Origin, daher tragen sie ASP.NET_SessionId automatisch. Ein Client ohne Cookie‑Speicher – ein Skript, ein Server‑zu‑Server‑Aufruf, ein Cross‑Origin‑Setup, das Cookies entfernt – wird abgelehnt. Das ist das funktionierende Feature.

UnsafeMode = true schaltet die Prüfung aus: jede Anfrage, die das Token trägt, wird bedient. Es ist ein globaler Schalter für jedes Dokument, ohne pro‑Dokument‑Überschreibung. Lassen Sie es false.

Widerruf

CloseDocument(token) tut mehr als Speicher freizugeben: es entfernt den secure-{token}‑Eintrag aus der Sitzung der aktuellen Anfrage und widerruft das Token, sodass ein geschlossenes Token sofort abgelehnt wird.

Web‑Farms: signierte Tickets

In einem Farm kann die nächste Anfrage auf einem Server landen, der das Dokument nie gesehen hat, in einem anderen Worker‑Prozess, mit seiner eigenen ASP.NET‑Sitzung. Die Sitzungs‑Gewährung kann ihr nicht folgen. Der verteilte Modus ersetzt sie durch ein signiertes Ticket, das an den Browser gebunden ist: jeder Knoten teilt einen Speicher für Dokumentensitzungen und einen Signaturschlüssel, und DocImage.axd akzeptiert eine Anfrage, wenn ihr Ticket für dieses Token, diesen Browser und – wenn der Benutzer angemeldet ist – diesen Benutzer gültig ist.

Die Einrichtung, identisch auf jedem Knoten:

csharp
// Global.asax.cs - Application_Start
Doconut.DoconutHost.Initialize(
    options => options.UnsafeMode = false,     // Die Ticket‑Überprüfung wird nur ausgeführt, wenn dies false ist
    services => services.AddDoconutDistributed(d =>
    {
        d.Store             = CloudLocation.FileShare;
        d.FileShareRootPath = @"\\fileserver\doconut-shared";  // Ein Ordner, den jeder Knoten erreichen kann
        d.SigningKey        = farmKey;                          // mindestens 32 Byte, bei jedem Knoten GLEICH
    }));

Der Öffnungs‑Endpunkt bindet dann das Ticket vor dem Öffnen an den Browser und gibt das Ticket zusammen mit dem Token zurück:

  • set DocOptions.BrowserId = DoconutFarmBinding.EnsureBrowserId(System.Web.HttpContext.Current, securityOptions) — es gibt das doconut-client‑Cookie aus, an das das Ticket gebunden ist — und DocOptions.UserId = DoconutFarmBinding.ResolveUserId(System.Web.HttpContext.Current);
  • nach OpenDocumentAsync, gib viewer.AccessToken zusammen mit dem Token zurück;
  • in der Seite übergebe beide an das Widget: objViewer.View(token, access).

Doconut.MvcSample.WebFarm im Beispielpaket ist ein vollständiger, ausführbarer Farm‑Knoten, und die danebenstehende Migrationsanleitung erklärt jeden Schritt.

Halten Sie den Signaturschlüssel außerhalb der Quellcodeverwaltung: er signiert sowohl die Tickets als auch die Dokumente im gemeinsamen Speicher. Ein Knoten mit einem anderen Schlüssel weist jedes Ticket, das die anderen ausgestellt haben, zurück.

Testen Sie einen Farm mit einem echten Browser oder einem Skript, das Cookies behält. Ein Client ohne das doconut-client‑Cookie wird nicht mit 401 beantwortet: er erhält das Fehlermotiv „not authorized“ mit Status 200, etwa 2 KB, während eine echte Seite Zehntausende bis Hunderttausende Kilobyte groß ist.

Produktions‑Checkliste

  • Behalten Sie UnsafeMode = false (die Standardeinstellung) bei.
  • Öffnen Sie Dokumente nur von Anfragen, die Sitzungszustand haben, und schalten Sie den Sitzungszustand niemals aus.
  • Stellen Sie sicher, dass das Sitzungs‑Cookie DocImage.axd erreicht (gleiche Herkunft, HTTPS, eine SameSite‑Richtlinie, die es erlaubt).
  • Verwenden Sie in einem Farm den verteilten Modus mit einem von allen Knoten geteilten Signaturschlüssel.
  • Rufen Sie CloseDocument auf, wenn der Benutzer ein Dokument verlässt – Speicher und Sicherheit profitieren beide.
  • Protokollieren oder teilen Sie Tokens niemals; behandeln Sie sie als kurzlebige Anmeldeinformationen.

War diese Seite hilfreich?