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

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

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

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

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

Время жизни

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

csharp
// Краткоживущая сессия для однократного предварительного просмотра
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 вместе с запросами страниц. Настройки кросс‑домена, которые удаляют cookie (или API‑клиент без cookie‑хранилища), не пройдут проверку — это работа функции, а не ошибка.
  • options.UnsafeMode = true полностью отключает привязку. Это предусмотрено для контролируемых сценариев; в продакшене на одном узле оставляйте значение false.

Обратите внимание на написание. В предыдущей библиотеке .NET Standard это свойство называлось UnSafeMode и передавалось в промежуточное ПО; здесь оно называется UnsafeMode и устанавливается один раз внутри AddDoconut().

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

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

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

  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 для безопасности документов Doconut.

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() пропускает промежуточное ПО доступа, и проверка маркера также отключается.

Безопасность при работе нескольких узлов

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

Ответом не является оставлять документы без защиты. Используйте подписанные билеты доступа через AddDoconutDistributedDocumentSecurity(...), которые заменяют проверку сессии на учётные данные, проверяемые каждым узлом независимо. Полное описание находится в Распределённые развертывания.

Отзыв

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

Чек‑лист для продакшена

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

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