Relace a zabezpečení

Relace dokumentů a řízení přístupu

Doconut token identifikuje otevřený dokument. Pokud by byla obsloužena jakákoli žádost, která jej nese, kdokoli, kdo jej získá, by mohl číst každou stránku. Tato stránka vysvětluje, co relace dokumentu obsahuje, jak dlouho žije a jak DocImage.axd rozhoduje, kdo může vidět její stránky — na jednom serveru i ve webové farmě.

Co obsahuje relace dokumentu

Každý úspěšný OpenDocumentAsync vytvoří jednu relaci, uchovávanou v paměti:

  • načtený prohlížeč formátu — instance enginu, která drží parsovaný dokument,
  • stav na stránce — otočení, převrácení a data anotací, která uživatel aplikuje ve widgetu,
  • volitelný index vyhledávání, vytvořený při prvním vyhledávání (nebo načtený z předem vytvořeného souboru .srh),
  • vodoznak relace z DocOptions.Watermark.

Životnost

Relace vyprší po posuvném okně: DocOptions.TimeOut minut (výchozí 60), resetuje se každou žádostí, která předloží token. Když relace končí — vypršením nebo CloseDocument(token) — je uvolněn její dokumentový engine a paměť je okamžitě uvolněna.

csharp
// Krátkodobá relace pro jednorázový náhled
var token = await viewer.OpenDocumentAsync(path, new DocOptions { TimeOut = 10 });

Žádost s vypršeným tokenem získá chybový obrázek s textem Document session not found. Please re-open document.. Stránka musí dokument otevřít znovu, aby získala nový token. Na jediném serveru recyklace aplikačního poolu také ukončí všechny relace.

Stránky jsou podávány pouze relaci, která je otevřela

S UnsafeMode = false — výchozí — otevření dokumentu uděluje přístup k ASP.NET relaci žádosti, která jej otevřela, zápisem položky secure-{token} do této relace. DocImage.axd vyžaduje samotný stav relace a podává stránku jen tehdy, když požadující relace obsahuje tuto položku. Jakýkoli jiný prohlížeč, který předloží stejný token, získá chybový obrázek s textem You Are Not Authorized To View This Page..

csharp
Doconut.DoconutHost.Initialize(options =>
{
    // false (výchozí): DocImage.axd slouží stránku pouze relaci ASP.NET, která ji otevřela
    // dokument. Handler požaduje stav relace sám; potřebuje jen, aby site ne
    // vypnul stav relace v Web.config.
    options.UnsafeMode = false;
});

Tři praktické důsledky:

  • Otevřený koncový bod potřebuje stav relace. MVC kontroléry a stránky Web Forms jej mají ve výchozím nastavení. Vlastní IHttpHandler jej nemá, pokud neimplementuje System.Web.SessionState.IRequiresSessionState. Otevření, které běží bez relace, nemá co udělit, takže prohlížeč zobrazuje „You Are Not Authorized To View This Page.“ na každé stránce.
  • Stav relace musí zůstat zapnutý. <sessionState mode="Off" /> v Web.config zakazuje jak udělení, tak kontrolu a každá stránka je odmítnuta.
  • Prohlížeč musí odesílat cookie relace. Požadavky widgetu jsou stejného původu, takže automaticky nesou ASP.NET_SessionId. Klient bez úložiště cookies — skript, volání server‑to‑server, nastavení cross‑origin, které odstraňuje cookies — je odmítnut. To je funkce v akci.

UnsafeMode = true vypíná kontrolu: každá žádost nesoucí token je obsloužena. Jedná se o jeden globální přepínač pro každý dokument, bez per‑dokumentového přepsání. Nechte ho false.

Revokace

CloseDocument(token) dělá víc než uvolnit paměť: odstraňuje položku secure-{token} ze současné žádosti relace a odvolává token, takže uzavřený token je okamžitě odmítnut.

Webové farmy: podepsané lístky

Ve farmě může další žádost dopadnout na server, který dokument nikdy neviděl, v jiném pracovním procesu, se svou vlastní ASP.NET relací. Udělení relace ho nemůže následovat. Distribuovaný režim jej nahrazuje podepsaný lístek svázaný s prohlížečem: každý uzel sdílí jedno úložiště pro relace dokumentů a jeden podpisový klíč, a DocImage.axd přijímá žádost, když je její lístek platný pro daný token, tento prohlížeč a — pokud je uživatel přihlášen — pro tohoto uživatele.

Nastavení, identické na každém uzlu:

csharp
// Global.asax.cs - Application_Start
Doconut.DoconutHost.Initialize(
    options => options.UnsafeMode = false,     // kontrola lístku se spouští pouze, když je to false
    services => services.AddDoconutDistributed(d =>
    {
        d.Store             = CloudLocation.FileShare;
        d.FileShareRootPath = @"\\fileserver\doconut-shared";  // složka, ke které může přistupovat každý node
        d.SigningKey        = farmKey;                          // alespoň 32 bajtů, STEJNÝ na každém node
    }));

Otevřený koncový bod pak sváže lístek s prohlížečem před otevřením a vrátí lístek spolu s tokenem:

  • nastavte DocOptions.BrowserId = DoconutFarmBinding.EnsureBrowserId(System.Web.HttpContext.Current, securityOptions) — vydá cookie doconut-client, ke které je lístek svázán — a DocOptions.UserId = DoconutFarmBinding.ResolveUserId(System.Web.HttpContext.Current);
  • po OpenDocumentAsync vraťte viewer.AccessToken spolu s tokenem;
  • na stránce předávejte oba widgetu: objViewer.View(token, access).

Doconut.MvcSample.WebFarm v balíčku vzorků je kompletní, spustitelný uzel farmy a migrační průvodce vedle něj vysvětluje každý krok.

Uchovávejte podpisový klíč mimo správu zdrojového kódu: podepisuje lístky i šifruje dokumenty ve sdíleném úložišti. Uzel s odlišným klíčem odmítá každý lístek, který vydaly ostatní.

Otestujte farmu skutečným prohlížečem nebo skriptem, který uchovává cookies. Klient bez cookie doconut-client nedostane odpověď 401: obdrží chybový obrázek „not authorized“ se stavem 200, asi 2 KB, zatímco skutečná stránka má desítky až stovky kilobytů.

Kontrolní seznam pro produkci

  • Udržujte UnsafeMode = false (výchozí).
  • Otevírejte dokumenty z žádostí, které mají stav relace, a nikdy nevypínejte stav relace.
  • Ujistěte se, že cookie relace dosáhne DocImage.axd (stejný původ, HTTPS, politika SameSite, která to umožňuje).
  • Ve farmě použijte distribuovaný režim s jedním podpisovým klíčem sdíleným všemi uzly.
  • Zavolejte CloseDocument, když uživatel opustí dokument — paměť i zabezpečení mají prospěch.
  • Nikdy neukládejte ani nesdílejte tokeny; považujte je za krátkodobé přihlašovací údaje.

Byla tato stránka užitečná?