Сессии и безопасность
Сессии документов и контроль доступа
Токен Doconut обладает большой мощью: любой, кто его предъявит, может запросить каждую страницу документа, если он не привязан к открывающей сессии. Эта страница объясняет, что хранит сессия, как долго она живёт и какие проверки UseDoconut() включает по умолчанию.
Что хранит сессия документа
Каждый успешный OpenDocumentAsync создаёт одну сессию в IMemoryCache:
- загруженный просмотрщик формата (экземпляр движка документа, содержащий разобранный документ),
- per-page state — вращение, отражения и данные аннотаций, которые пользователь применяет в виджете,
- опциональный поисковый индекс, создаётся лениво при первом поиске (или загружается из заранее построенного файла
.srhв сценариях веб‑фермы), - метка watermark сессии из
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 вместе с запросами страниц. Настройки кросс‑origin, которые удаляют cookies (или API‑клиент без cookie‑jar), не пройдут проверку — это работа функции, а не баг.
options.UnsafeMode = trueполностью отключает привязку. Она существует для контролируемых сценариев (например, рендеринг сервер‑к‑серверу); оставьте еёfalseв продакшене.
Привязка токена контролируется исключительно этим глобальным переключателем UnsafeMode — он включён по умолчанию (UnsafeMode = false) и применяется ко всем сессиям. Нет возможности отключить её для отдельного документа; установка UnsafeMode = true отключает привязку глобально.
Права доступа и аутентифицированные пользователи
Когда UnsafeMode имеет значение false, UseDoconut() автоматически вставляет DocumentAccessMiddleware перед промежуточным ПО страниц. Не регистрируйте его повторно. Когда запрос содержит токен, он ищет access grant, записанный при открытии документа, и авторизует только если выполнены все следующие условия:
- существует грант для токена,
- он не истёк (срок гранта =
TimeOutдокумента), - ID ASP.NET‑сессии, сделавшей запрос, совпадает с тем, который открыл документ,
- если открывший был аутентифицирован, то требование пользователя
NameIdentifierтакже совпадает.
При ошибках возвращается 403 — в виде PNG‑изображения ошибки для запросов страниц/миниатюр, иначе в виде обычного текста. Сообщение и параметр запроса токена берутся из DocumentSecurityOptions (TokenQueryKey, по умолчанию "token"; UnauthorizedMessage, по умолчанию "You Are Not Authorized To View This Page."). Настройте эти параметры через ASP.NET Core DI перед построением приложения. Если состояние сессии недоступно, промежуточное ПО закрывается с ошибкой 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.";
});Основное промежуточное ПО страниц затем проверяет маркер сессии secure-{token} перед обслуживанием документа. С UnsafeMode = true, UseDoconut() пропускает промежуточное ПО доступа, и проверка основного маркера также отключена.
Отзыв
CloseDocument(token) не только освобождает память — он также удаляет маркер secure-{token} и отзывает право доступа, поэтому закрытый токен сразу становится недействительным на обоих уровнях безопасности.
Чеклист для продакшна
- Оставьте
UnsafeMode = false(по умолчанию) — этот глобальный переключатель привязывает токены к сессиям. - Зарегистрируйте
AddDistributedMemoryCache()(приложения MVC и Razor Pages уже имеют его) иAddSession(), и вызовитеapp.UseSession()перед веткой промежуточного ПО Doconut. - Убедитесь, что ваша политика cookie сессии позволяет запросам виджета передавать cookie (
SameSite, HTTPS). - Используйте
CloseDocument, когда пользователь покидает документ — это улучшает память и безопасность. - Никогда не журналируйте и не делитесь токенами; рассматривайте их как краткосрочные учётные данные.
Была ли эта страница полезной?