Сессии и безопасность

Сессии документов и контроль доступа

Токен Doconut обладает большой силой: любой, кто его предъявит, может запросить любую страницу документа, если он не привязан к открывающей сессии. Эта страница объясняет, что хранится в сессии, как долго она живёт и какие проверки включаются по умолчанию функцией UseDoconut().

Что хранит сессия документа

Каждый успешный OpenDocumentAsync создаёт одну сессию в IMemoryCache:

  • загруженный просмотрщик формата (экземпляр движка документа, содержащий разобранный документ),
  • состояние каждой страницы — вращение, отражения и данные аннотаций, которые пользователь применяет в виджете,
  • необязательный поисковый индекс, создаваемый лениво при первом поиске (или загружаемый из заранее построенного файла .srh в сценариях веб‑фермы),
  • водяной знак сессии, полученный из DocOptions.Watermark.

Время жизни

Сессии истекают по скользящему окну: DocOptions.TimeOut минут (по умолчанию 60), сбрасываемому каждым запросом, предъявляющим токен. Когда сессия удаляется — из‑за истечения срока или вызова CloseDocument(token) — её callback освобождает движок документа и сразу освобождает связанную память.

csharp
// Краткоживущая сессия для однократного предварительного просмотра
var token = await viewer.OpenDocumentAsync(path, new DocOptions { TimeOut = 10 });

Запрос с истёкшим токеном получает изображение ошибки с текстом Document session not found. Please re-open document. — клиент должен открыть документ заново, чтобы получить новый токен.

Встроенная привязка токенов

При UnsafeMode = false (по умолчанию) OpenDocumentAsync привязывает новый токен к сессии ASP.NET HTTP‑запроса, который его открыл, записывая маркер secure-{token} в эту сессию. Промежуточное ПО Doconut затем отказывает в обслуживании страниц любой другой сессии браузера:

  • Другой браузер/сессия, предъявляющая украденный токен → изображение ошибки You Are Not Authorized To View This Page.
  • Промежуточное ПО сессии не зарегистрировано → HTTP 500 Session middleware not configured. Call UseSession() before UseDoconut().

Именно поэтому в Quick Start настоятельно рекомендуется вызвать AddSession() + app.UseSession() перед веткой Doconut. Два практических следствия:

  • Клиент должен отправлять cookie сессии ASP.NET вместе с запросами страниц. Настройки кросс‑домена, которые удаляют cookie (или API‑клиент без cookie‑хранилища), не пройдут проверку — это работа функции, а не ошибка.
  • options.UnsafeMode = true полностью отключает привязку. Она существует для контролируемых сценариев (например, рендеринг сервер‑к‑серверу); оставляйте её false в продакшене.

Привязка токенов контролируется исключительно этим глобальным переключателем UnsafeMode — он включён по умолчанию (UnsafeMode = false) и применяется ко всем сессиям. Нет возможности отключить её для отдельного документа; установка UnsafeMode = true отключает привязку глобально.

Права доступа и аутентифицированные пользователи

Когда UnsafeMode установлен в false, UseDoconut() автоматически вставляет DocumentAccessMiddleware перед промежуточным ПО страниц. Не регистрируйте его повторно. Когда запрос содержит токен, он ищет право доступа, записанное при открытии документа, и авторизует только при выполнении всех условий:

  1. существует право доступа для токена,
  2. оно не истекло (срок действия права = TimeOut документа),
  3. ID запрашиваемой сессии ASP.NET совпадает с тем, который открыл документ,
  4. если открывший был аутентифицирован, то утверждение NameIdentifier запрашивающего пользователя также совпадает.

При ошибках возвращается 403 — в виде PNG‑изображения ошибки для запросов страниц/миниатюр, иначе в виде обычного текста. Сообщение и ключ запроса токена берутся из DocumentSecurityOptions (TokenQueryKey, по умолчанию "token"; UnauthorizedMessage, по умолчанию "You Are Not Authorized To View This Page."). Настройте эти параметры через DI ASP.NET Core перед построением приложения. Если состояние сессии недоступно, промежуточное ПО закрывается с ошибкой 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.";
});

Основное промежуточное ПО страниц затем проверяет маркер secure-{token} в сессии перед обслуживанием документа. При UnsafeMode = true UseDoconut() пропускает промежуточное ПО доступа, и проверка маркера также отключается.

Отзыв

CloseDocument(token) не только освобождает память — он также удаляет маркер secure-{token} и отзывает право доступа, так что закрытый токен сразу становится недействительным на обоих уровнях безопасности.

Список проверок для продакшена

  • Оставляйте UnsafeMode = false (по умолчанию) — этот глобальный переключатель привязывает токены к сессиям.
  • Регистрируйте AddSession() и вызывайте app.UseSession() перед веткой промежуточного ПО Doconut.
  • Убедитесь, что политика cookie сессии позволяет запросам виджета передавать cookie (SameSite, HTTPS).
  • Используйте CloseDocument, когда пользователь покидает документ — это выгодно и для памяти, и для безопасности.
  • Никогда не записывайте в логи и не делитесь токенами; рассматривайте их как краткосрочные учётные данные.

Была ли эта страница полезной?