授权

功能、授权层级与授权服务

此页面是运行时参考,说明授权如何影响 Doconut 的行为:每种授权状态允许的操作、功能如何授予,以及如何在代码中检查所有这些内容。(有关加载授权,请参见 授权设置。)

授权状态及其作用

状态是否可以打开文档?水印功能
完整(付费)授权(在其订阅/更新窗口内)是无已购买的(Has* 标志)
临时授权(开发者/NFR — 评估授权,在其到期日前)是无全部 — 统一授予(评估渠道)
已过期(临时授权超过到期日,或付费订阅超过续订日期)是评估水印未授予任何
根本没有授权文件是评估水印未授予任何
找到但被拒绝(签名无效、被篡改、列入黑名单,或构建版本高于授权的版本窗口)不 — 每次打开时抛出 LicenseException——

值得内部化的两点结论:

  • 缺失授权并不等同于临时授权。 没有授权文件时,页面会带水印渲染,且没有任何功能(搜索、批注、插件)被激活。完整、无水印的体验需要实际的 临时授权(获取一个)。
  • 只有被拒绝的授权会阻止打开。 日历/订阅到期会降级为带水印渲染;但部署一个 高于 授权版本窗口的构建会被拒绝,并 快速失败,抛出 LicenseException,因此你可以在部署时捕获,而不是悄悄地发布带水印的输出。该异常(来自 OpenDocumentAsync)携带 License.RejectionMessage 中的原因。

功能

Doconut 通过 功能(capability)来控制可选功能。当前这些包括可选的 Converter 和 DICOM 插件以及内置的 Search 与 Annotation 功能,均由授权授予。基础查看器本身不是功能——它是前置条件,以 IsViewerLicensed 形式呈现:

csharp
bool viewerLicensed = lic.IsViewerLicensed; // non-TRIAL license present AND covering this build's version

整个管道使用的唯一门控是 IsCapabilityGranted:

csharp
bool searchGranted = lic.IsCapabilityGranted(LicenseCapability.Search);

其逻辑,直接取自实现:一个有效(未过期)的 临时 授权会授予 所有 功能——包括尚未拥有专用购买标志的功能;而真实的付费授权仅授予其 Has* 标志,并对未映射的功能采用 默认拒绝。(TRIAL 类型的旧文件 不 构成权益——它被视为未授权:带水印,未授予任何功能。)

临时授权

临时(开发者/NFR)授权通过 ExpiryNote 标记,并携带硬性到期日期:

成员含义
IsTemporary存在 ExpiryNote 标记(通过标记存在性检测——永不匹配标记文本,文本是动态的)
ExpiryNote授权中嵌入的说明性文本
LicenseExpiry硬性到期日期(DateTime?)

不同层级的到期语义不同:临时授权仅在其 LicenseExpiry 日期 失效(其订阅窗口被忽略;缺少日期的临时授权被视为已过期,安全失效)。其他所有授权均在其订阅/更新窗口日期失效。

IDoconutLicenseService 参考

从 DoconutHost.Services 中解析 IDoconutLicenseService(命名空间 Doconut.Core.Interfaces)。它是单例——授权在 DoconutHost.Initialize 中解析一次:

成员含义
License完整的 DoconutLicenseInfo 快照(见下)
IsTrial旧的 TRIAL 类型文件(视为未授权——不构成权益)
IsTemporary / ExpiryNote / LicenseExpiry临时授权标记
IsExpired根据上述层级规则已过期
IsVersionValid当前构建位于授权的支持窗口内
IsViewerLicensed找到非 TRIAL 文件 且 版本受覆盖——基础前置条件
IsCapabilityGranted(cap)单一功能门控
HasSearch HasAnnotation HasConverter HasDicom按功能的购买标志——对临时授权请使用 IsCapabilityGranted 获取答案
IsValidForDomain(host)主机覆盖范围;V4 授权使用通配符 *.*
LicenseRejectionReason非空 ⇒ 打开被此消息阻止

DoconutLicenseInfo 向管理面板提供友好的显示快照:Owner、Email、LicenseType、Domain、IsLicenseFileFound、IsVersionValid、IsTrial、IsExpired、Has* 标志、临时授权字段以及 RejectionMessage。

csharp
// GET /Features - feature-flag your UI from the same source of truth the SDK uses
public ActionResult Index()
{
    var lic = Doconut.DoconutHost.Services.GetRequiredService<IDoconutLicenseService>();

    return Json(new
    {
        viewer     = lic.IsViewerLicensed || lic.IsTemporary,
        search     = lic.IsCapabilityGranted(LicenseCapability.Search),
        annotation = lic.IsCapabilityGranted(LicenseCapability.Annotation),
        conversion = lic.HasConverter,
        dicom      = lic.HasDicom,
    }, JsonRequestBehavior.AllowGet);
}

健康检查

Doconut 注册了一个 "doconut" 健康检查,用于报告授权状态。经典 ASP.NET 本身没有健康端点,因此需要在控制器中暴露它:

csharp
// GET /Health - Doconut registers a "doconut" health check that reports the license state:
// Healthy (valid), Degraded (trial or no license file), Unhealthy (expired).
public async Task<ActionResult> Index()
{
    var health = Doconut.DoconutHost.Services.GetRequiredService<HealthCheckService>();
    HealthReport report = await health.CheckHealthAsync();

    Response.StatusCode = report.Status == HealthStatus.Unhealthy ? 503 : 200;
    return Content(report.Status.ToString(), "text/plain");
}

将其接入监控后,订阅即将到期时会触发警报,而不是产生支持工单。参见 DoconutHost 获取状态值。

版本升级

授权覆盖一个 版本窗口。将 NuGet 包更新到 高于 该窗口的构建会使授权对该构建失效:IsVersionValid 变为 false,并 通过 LicenseException 阻止打开(原因在 License.RejectionMessage 中)——故意快速失败,以便在部署时捕获陈旧或未授权的构建,而不是悄悄地对生产输出加水印。续订订阅、在 wwwroot 中替换 .lic,并回收应用池,使 DoconutHost.Initialize 加载新授权。

此页面对您有帮助吗?