会话与安全

文档会话和访问控制

Doconut 令牌功能强大:如果不绑定到打开会话,任何持有它的人都可以请求文档的每一页。本页解释了会话保存了什么、它的存活时间以及 UseDoconut() 默认启用的检查。

文档会话保存的内容

每次成功的 OpenDocumentAsync 会在 IMemoryCache 中创建一个会话:

  • 已加载的 格式查看器(持有已解析文档的文档引擎实例),
  • 每页状态 — 用户在小部件中应用的旋转、翻转和注释数据,
  • 可选的 搜索索引,在首次搜索时惰性构建(或在 Web 农场场景中从预构建的 .srh 文件加载),
  • 会话的 水印,来源于 DocOptions.Watermark

生命周期

会话在 滑动窗口 中过期:DocOptions.TimeOut 分钟(默认 60),每次携带令牌的请求都会重置。当会话被驱逐——无论是因超时还是通过 CloseDocument(token)——其驱逐回调会立即释放文档引擎并释放相关内存。

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

使用已过期令牌的请求会收到错误图片,显示 Document session not found. Please re-open document. —— 客户端必须重新打开文档以获取新的令牌。

内置令牌绑定

UnsafeMode = false(默认值)时,OpenDocumentAsync 会将新令牌绑定到打开它的 HTTP 请求的 ASP.NET 会话,通过在该会话中写入 secure-{token} 标记实现。随后 Doconut 中间件会拒绝向任何其他浏览器会话提供页面:

  • 不同的浏览器/会话使用被盗令牌 → 错误图片 You Are Not Authorized To View This Page.
  • 未注册会话中间件 → HTTP 500 Session middleware not configured. Call UseSession() before UseDoconut().

这就是快速入门坚持在 Doconut 分支之前使用 AddSession() + app.UseSession() 的原因。两个实际后果:

  • 客户端必须在页面请求中发送 ASP.NET 会话 Cookie。跨域设置如果剥离 Cookie(或 API 客户端没有 Cookie 桶)将导致检查失败——这属于功能正常,而非 bug。
  • options.UnsafeMode = true 会完全禁用绑定。它用于受控场景(例如服务器到服务器的渲染);在生产环境中请保持为 false

令牌绑定仅由全局 UnsafeMode 开关控制——默认开启(UnsafeMode = false),并适用于每个会话。没有针对单个文档的关闭选项;将 UnsafeMode = true 会全局禁用绑定。

访问授权与已认证用户

UnsafeModefalse 时,UseDoconut() 会自动在页面中间件之前插入 DocumentAccessMiddleware。不要再次注册它。当请求携带令牌时,它会查找文档打开时记录的 访问授权,仅在以下全部满足时才授权:

  1. 令牌存在授权;
  2. 授权未过期(授权生命周期等于文档的 TimeOut);
  3. 请求的 ASP.NET 会话 ID 与打开文档的会话 ID 匹配;
  4. 如果打开者已认证,请求用户的 NameIdentifier 声明也必须匹配。

失败时返回 403 —— 对页面/缩略图请求返回 PNG 错误图片,其他情况返回纯文本。消息和令牌查询键来源于 DocumentSecurityOptionsTokenQueryKey,默认 "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.

csharp
builder.Services.Configure<Doconut.Security.DocumentSecurityOptions>(options =>
{
    options.TokenQueryKey = "token";
    options.UnauthorizedMessage = "You Are Not Authorized To View This Page.";
});

核心页面中间件随后在提供文档之前验证 secure-{token} 会话标记。若 UnsafeMode = trueUseDoconut() 会跳过访问中间件,核心标记检查也会被禁用。

撤销

CloseDocument(token) 不仅释放内存——还会移除 secure-{token} 标记并撤销访问授权,因此被关闭的令牌会立即在两个安全层面失效。

生产环境检查清单

  • 保持 UnsafeMode = false(默认)——此全局开关负责将令牌绑定到会话。
  • 在 Doconut 中间件分支之前注册 AddSession() 并调用 app.UseSession()
  • 确保会话 Cookie 策略允许小部件的请求携带 Cookie(SameSite、HTTPS)。
  • 用户离开文档时使用 CloseDocument —— 既可释放内存,又可提升安全。
  • 切勿记录或共享令牌;将其视为短期凭证。

此页面有帮助吗?