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

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

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

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

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

Время жизни

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

csharp
// A short-lived session for a one-shot preview
var token = await viewer.OpenDocumentAsync(path, new DocOptions { TimeOut = 10 });

Запрос с истёкшим токеном получает изображение ошибки с надписью Сессия документа не найдена. Пожалуйста, откройте документ заново. — клиент должен открыть документ заново, чтобы получить новый токен.

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

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

  • Другая браузер/сессия, предъявляющая украдённый токен → изображение ошибки У вас нет прав для просмотра этой страницы.
  • Промежуточное ПО сессии не зарегистрировано → HTTP 500 Промежуточное ПО сессии не настроено. Вызовите UseSession() перед UseDoconut().

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

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

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

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

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

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

При ошибках возвращается 403 — в виде PNG‑изображения ошибки для запросов страниц/миниатюр, иначе в виде обычного текста. Сообщение и ключ запроса токена берутся из DocumentSecurityOptions (TokenQueryKey, по умолчанию "token"; UnauthorizedMessage, по умолчанию "У вас нет прав для просмотра этой страницы."). Настройте эти параметры через DI ASP.NET Core до построения приложения. Если состояние сессии недоступно, промежуточное ПО закрывается с ошибкой HTTP 500: Для безопасности документов Doconut требуется сессия ASP.NET.

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, когда пользователь покидает документ — это выгодно и для памяти, и для безопасности.
  • Никогда не журналируйте и не делитесь токенами; рассматривайте их как краткоживущие учётные данные.

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