Sessioni e Sicurezza

Sessioni di documento e controllo accessi

Un token Doconut è potente: chi lo presenta potrebbe richiedere ogni pagina del documento se non fosse legato alla sessione di apertura. Questa pagina spiega cosa contiene una sessione, quanto dura e i controlli che UseDoconut() abilita per impostazione predefinita.

Cosa contiene una sessione di documento

Ogni chiamata riuscita a OpenDocumentAsync crea una sessione in IMemoryCache:

  • il visualizzatore di formato caricato (l'istanza del motore del documento che contiene il documento analizzato),
  • stato per pagina — rotazione, capovolgimenti e dati di annotazione che l'utente applica nel widget,
  • l'indice di ricerca opzionale, costruito pigramente al primo ricerca (o caricato da un file .srh pre-costruito quando le pagine sono servite da storage condiviso),
  • il watermark della sessione da DocOptions.Watermark.

Durata

Le sessioni scadono su una finestra scorrevole: DocOptions.TimeOut minuti (predefinito 60), resettata da ogni richiesta che presenta il token. Quando una sessione viene espulsa — per scadenza o da CloseDocument(token) — la sua callback di espulsione elimina il motore del documento e libera immediatamente la memoria associata.

csharp
// Una sessione a vita breve per un'anteprima unica
var token = await viewer.OpenDocumentAsync(path, new DocOptions { TimeOut = 10 });

Una richiesta con un token scaduto ottiene un'immagine di errore che legge Document session not found. Please re-open document. — il client deve riaprire per ottenere un token nuovo.

Binding del token integrato

Con UnsafeMode = false (il valore predefinito), OpenDocumentAsync lega il nuovo token alla sessione ASP.NET della richiesta HTTP che lo ha aperto, scrivendo un marcatore secure-{token} in quella sessione. Il middleware Doconut rifiuta quindi di servire pagine a qualsiasi altra sessione del browser:

  • Browser/session diverso che presenta un token rubato → immagine di errore You Are Not Authorized To View This Page.
  • Middleware di sessione non registrato → HTTP 500 Session middleware not configured. Call UseSession() before UseDoconut().

Questo è il motivo per cui il Quick Start insiste su AddSession() + app.UseSession() prima del ramo Doconut. Due conseguenze pratiche:

  • Il client deve inviare il cookie di sessione ASP.NET con le richieste di pagina. Configurazioni cross-origin che rimuovono i cookie (o un client API senza contenitore di cookie) falliranno il controllo — è una funzionalità che funziona, non un bug.
  • options.UnsafeMode = true disabilita completamente il binding. Esiste per scenari controllati; lasciarlo false in produzione su un singolo nodo.

Nota l'ortografia. La precedente libreria .NET Standard chiamava questa proprietà UnSafeMode e la passava al middleware; qui è UnsafeMode e viene impostata una sola volta all'interno di AddDoconut().

Il binding del token è controllato esclusivamente da questo interruttore globale UnsafeMode — è attivo per impostazione predefinita (UnsafeMode = false) e si applica a ogni sessione. Non esiste un'opzione di esclusione per documento; impostare UnsafeMode = true disabilita il binding a livello globale.

Concessioni di accesso e utenti autenticati

Quando UnsafeMode è false, UseDoconut() inserisce automaticamente il middleware di accesso al documento prima del middleware di pagina. Non registrarlo una seconda volta. Quando una richiesta porta un token, cerca la concessione di accesso registrata al momento dell'apertura del documento e autorizza solo se tutti questi requisiti sono soddisfatti:

  1. esiste una concessione per il token,
  2. non è scaduta (durata della concessione = il TimeOut del documento),
  3. l'ID della sessione ASP.NET richiedente corrisponde a quello che ha aperto il documento,
  4. se chi ha aperto era autenticato, anche il claim NameIdentifier dell'utente richiedente corrisponde.

I fallimenti restituiscono 403 — come immagine PNG di errore per richieste di pagina/miniatura, come testo semplice altrimenti. Il messaggio e la chiave di query del token provengono da DocumentSecurityOptions (TokenQueryKey, predefinito "token"; UnauthorizedMessage, predefinito "You Are Not Authorized To View This Page."). Configura queste opzioni tramite ASP.NET Core DI prima di costruire l'app. Se lo stato della sessione non è disponibile, il middleware chiude con HTTP 500: ASP.NET Session is required for Doconut document security.

csharp
builder.Services.Configure<Doconut.Security.DocumentSecurityOptions>(options =>
{
    options.TokenQueryKey = "token";
    options.UnauthorizedMessage = "You Are Not Authorized To View This Page.";
});

Il middleware di pagina principale verifica quindi il marcatore di sessione secure-{token} prima di servire il documento. Con UnsafeMode = true, UseDoconut() salta il middleware di accesso e anche il controllo del marcatore principale è disabilitato.

Sicurezza su più nodi

I token legati a sessione presumono che il nodo che serve una pagina abbia anche visto la richiesta che ha aperto il documento. Questa supposizione non vale quando più nodi servono gli stessi documenti da storage condiviso: una richiesta di pagina può arrivare su un nodo che non ha mai visto l'apertura, e il controllo per sessione la rifiuta.

La risposta non è lasciare i documenti non protetti. Usa ticket di accesso firmati tramite AddDoconutDistributedDocumentSecurity(...), che sostituisce il controllo di sessione con una credenziale che ogni nodo può verificare in modo indipendente. L'intera configurazione è descritta in Distribuzioni distribuite.

Revoca

CloseDocument(token) non libera solo la memoria — rimuove anche il marcatore secure-{token} e revoca la concessione di accesso, quindi un token chiuso è morto su entrambi i livelli di sicurezza immediatamente.

Checklist per la produzione

  • Mantieni UnsafeMode = false (il valore predefinito) su un singolo nodo — questo interruttore globale è ciò che lega i token alle sessioni.
  • Registra AddDistributedMemoryCache() (le app MVC e Razor Pages lo hanno già) e AddSession(), e chiama app.UseSession() prima del ramo middleware Doconut.
  • Assicurati che la tua politica dei cookie di sessione consenta alle richieste del widget di trasportare il cookie (SameSite, HTTPS).
  • Usa CloseDocument quando l'utente lascia il documento — memoria e sicurezza ne traggono beneficio.
  • Non registrare né condividere mai i token; trattali come credenziali a breve durata.
  • Servi da storage condiviso? Passa a ticket di accesso firmati invece di accettare documenti non protetti.

Questa pagina è stata utile?