Сеансы и безопасность
Сеансы документов и контроль доступа
Токен Doconut обладает большой силой: любой, кто его предъявит, может запросить каждую страницу документа, если он не привязан к открывающему сеансу. Эта страница объясняет, что хранится в сеансе, как долго он живёт и какие проверки включаются по умолчанию функцией UseDoconut().
Что содержит сеанс документа
Каждый успешный вызов OpenDocumentAsync создаёт один сеанс в IMemoryCache:
- загруженный просмотрщик формата (экземпляр движка документа, содержащий разобранный документ),
- состояние каждой страницы — вращение, отражения и данные аннотаций, которые пользователь применяет в виджете,
- необязательный поисковый индекс, создаваемый лениво при первом поиске (или загружаемый из предварительно построенного файла
.srhв сценариях веб‑ферм), - водяной знак сеанса из
DocOptions.Watermark.
Время жизни
Сеансы истекают по скользящему окну: DocOptions.TimeOut минут (по умолчанию 60), сбрасываемому каждым запросом, предъявляющим токен. Когда сеанс удаляется — по истечении срока или через CloseDocument(token) — его callback освобождает движок документа и сразу же освобождает связанную память.
// Краткоживущий сеанс для однократного предварительного просмотра
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 перед промежуточным ПО страниц. Не регистрируйте его повторно. Когда запрос содержит токен, middleware ищет право доступа, записанное при открытии документа, и авторизует только при выполнении всех условий:
- существует грант для токена,
- он не истёк (время жизни гранта =
TimeOutдокумента), - идентификатор ASP.NET‑сеанса запроса совпадает с тем, который открыл документ,
- если открывший был аутентифицирован, claim
NameIdentifierзапрашивающего пользователя также совпадает.
При несоответствии возвращается 403 — в виде PNG‑изображения ошибки для запросов страниц/миниатюр, иначе в виде простого текста. Сообщение и ключ запроса токена берутся из DocumentSecurityOptions (TokenQueryKey, по умолчанию "token"; UnauthorizedMessage, по умолчанию "You Are Not Authorized To View This Page."). Настройте эти параметры через DI ASP.NET Core до построения приложения. Если состояние сеанса недоступно, middleware закрывается с ошибкой HTTP 500: ASP.NET Session is required for Doconut document security.
builder.Services.Configure<Doconut.Security.DocumentSecurityOptions>(options =>
{
options.TokenQueryKey = "token";
options.UnauthorizedMessage = "You Are Not Authorized To View This Page.";
});Ядро middleware страниц затем проверяет маркер secure-{token} в сеансе перед обслуживанием документа. При UnsafeMode = true UseDoconut() пропускает middleware доступа, и проверка маркера также отключается.
Отзыв
CloseDocument(token) не только освобождает память — он также удаляет маркер secure-{token} и отзывает право доступа, поэтому закрытый токен сразу становится недействительным на обоих уровнях безопасности.
Чеклист для продакшна
- Оставляйте
UnsafeMode = false(по умолчанию) — этот глобальный переключатель привязывает токены к сеансам. - Регистрируйте
AddDistributedMemoryCache()(в MVC и Razor Pages приложениях он уже есть) иAddSession(), и вызывайтеapp.UseSession()перед веткой промежуточного ПО Doconut. - Убедитесь, что политика cookie сеанса позволяет запросам виджета передавать cookie (
SameSite, HTTPS). - Используйте
CloseDocument, когда пользователь покидает документ — это выгодно и для памяти, и для безопасности. - Никогда не логируйте и не делитесь токенами; рассматривайте их как краткоживущие учётные данные.
Была ли эта страница полезной?