跳转到内容
getnextpdf.com

Enterprise 版本

SaaS

NextPDF Enterprise 为多租户 SaaS 部署提供了构件:一个不可变的租户上下文、带校验和与时序安全验证的限定 scope API key、一个带 80%/100% 行为的请求前配额检查,以及一个面向外部计费提供方的基于拉取的计量同步。本页描述可观察行为与公开契约。

此能力随 NextPDF Enterprisenextpdf/enterprise)发布,并通过一个 Enterprise 层级的授权信封激活。没有该授权的部署不会加载此能力的类。对比各版本并获取授权

SaaS 多租户面是一项 Enterprise 基础能力,只要安装了该包即可使用;不存在单独的按功能划分的标志。

一个租户由一个不可变的租户上下文表示:一个租户标识符、解析它的来源(一个 token、双向 TLS 或一个 API key),以及一组已授权的 scope。租户身份始终从经过认证的上下文解析——绝不从客户端提供的 header 或查询参数解析。单租户部署使用一个具有完整 scope 的固定默认上下文。

API key 携带一个用于区分 production 与 sandbox 的人类可读前缀、一段高熵随机主体,以及一段短校验和。校验和是一项快速便于拒绝笔误的便利措施,而不是安全机制——它让格式错误的 key 在任何数据存储查询之前就被拒绝。认证会验证校验和、用 SHA-256 对 key 做哈希、在仓库中按哈希查询,并拒绝未知、已吊销或已过期的 key。Key 绝不以明文记录或存储,而所存储的值即是哈希。Scope 强制是显式的:可以要求某个上下文持有某个给定 scope。

配额检查器在一个请求继续进行之前运行。它读取该租户的当期用量,在软限制(80%)处通过一个调用方提供的告警回调发出告警,并在硬限制(100%)处以一个携带重置时刻的“配额超限”状况拒绝。周期重置是 UTC 下的下个月边界。

计量同步适配器从部署的权威用量来源拉取用量事件,将它们转换为计费提供方的计量事件形态并附上一个稳定的幂等键,然后发送它们。失败的事件被路由到一个死信回调,且同步器跟踪一个每来源游标,使一个同步周期从上一次停止之处恢复。计费提供方集成是一个接口,因此提供方是可替换的。

起关键作用的决策是:NextPDF 发布的是强制执行原语,而不是一个托管平台。TenantContextApiKeyAuthenticatorQuotaChecker 与计量同步适配器都是你的部署接入其自有存储的契约。租户身份仅从经过认证的上下文解析,因此客户端永远无法通过一个 header 主张它自己的租户。Key 以 SHA-256 哈希形式存在于你的仓库中,配额读取你的用量来源,而计费提供方是一个可替换的接口。NextPDF 不持久化任何东西,因此租户数据、key 与计费都由你掌控。由于此面通过 Core 契约解析,同一段调用代码可在 Core、Pro 或 Enterprise 上运行——版本升级绝不会重写集成代码。

设计背景:开放内核,无锁定

Terminal window
composer require nextpdf/enterprise:^3

受支持的集成点是租户上下文(hasScopehasAnyScopesingleTenant)、API key 生成器(generateLivegenerateTestvalidateChecksumhashKeyisLiveKeyisTestKey)、API key 认证器(authenticaterequireScope)、API key 仓库接口、配额检查器(check)、租户配额值对象,以及计量同步适配器接口。请为生产环境提供持久化的仓库与计费适配器实现。

use NextPDF\Enterprise\SaaS\ApiKey\ApiKeyAuthenticator;
use NextPDF\Enterprise\SaaS\ApiKey\ApiKeyScope;
$tenant = $authenticator->authenticate($request->header('X-API-Key'));
$authenticator->requireScope($tenant, ApiKeyScope::Write);
// $tenant->tenantId is now safe to use as the billing/metering subject.
use NextPDF\Enterprise\SaaS\Quota\QuotaChecker;
use NextPDF\Enterprise\SaaS\Quota\QuotaExceededException;
$checker = new QuotaChecker($usageMeter, $logger, $alertCallback);
try {
$status = $checker->check($tenant, $tenantQuota);
if ($status['warning_percentage'] !== null) {
$response = $response->withHeader('X-Quota-Warning', (string) $status['warning_percentage']);
}
} catch (QuotaExceededException $e) {
return $this->quotaExceeded($e->resetsAt); // 100% — reject with reset instant
}
  • 校验和不是安全机制。 校验和通过只意味着 key 格式正确;认证仍会哈希并查询它,并强制执行吊销与过期。
  • 时序安全比较。 key 验证使用恒定时间比较;不要在某个包装层中重新引入会短路的字符串比较。
  • 租户身份来源。 绝不从客户端提供的 header 或查询值构造一个租户上下文;只从经过认证的上下文解析它。
  • 配额告警 vs 拒绝。 80% 告警并让请求继续进行(带一个告警百分比);100% 以重置时刻拒绝。告警回调应按周期去重。
  • 同步韧性。 一次计量同步拉取失败会返回一个无操作周期并保留游标;失败的单个事件会进入死信回调,而非阻塞整个周期。

租户上下文检查与校验和验证是恒定时间的。认证代价为一次哈希加一次仓库查询。配额检查代价为一次用量读取加恒定时间的算术运算。计量同步是一个按计划运行、脱离请求路径的批处理操作。

API key 仅以 SHA-256 哈希形式存储,且绝不以明文记录到日志;验证是时序安全的;已吊销与已过期的 key 以不同的结果被拒绝。租户身份必须来自经过认证的上下文。为组件间调用铸造的短期服务 token 携带标准的注册声明与一个短过期时间。本页仅描述行为;token 验证内部机制不属于公开契约。

  • 组件间服务 token 携带注册声明 issaudsubexpjti,并遵守 RFC 7519(JWT)§4.1.4 的 exp not-after 规则。
  • 服务 token 使用 RFC 7515(JSON Web Signature)§3.1 的 JWS compact serialization 三元组。
  • API key 以 SHA-256 摘要(FIPS 180-4 SHA-256)存储。注意:本页未从 RAG 语料库检索 FIPS 180-4;该算法是代码声明(hash('sha256', …)),此处标注为代码声明而非 RAG 已验证。
  • 一个租户是一个不可变的上下文(租户 id、解析来源、已授权 scope);身份始终从经过认证的上下文解析,绝不从客户端提供的 header 或查询值解析。
  • API key 认证会验证校验和、用 SHA-256 哈希、按哈希查询,并以不同的结果拒绝未知、已吊销或已过期的 key;key 绝不以明文记录或存储,且验证是时序安全的。
  • 配额检查器在 80% 处通过调用方提供的回调告警,并在 100% 处以一个携带重置时刻(下个月边界,UTC)的“配额超限”状况拒绝。
  • 一次计量同步拉取失败会返回一个无操作周期并保留每来源游标;失败的单个事件路由到死信回调,而非阻塞整个周期。
  • 校验和是一项便于拒绝笔误的便利措施,而不是安全机制。

本页仅记录外部可观察行为与受支持的公开 API 面。内部命名空间路径、辅助类、机制表、runbook 文件名与工单前缀不在范围之内。

NextPDF Core(Apache-2.0)没有任何租户、API key 或配额面——完全没有;此能力在 Core 层级没有对应物。

NextPDF Pro 没有任何租户、API key 或配额面——完全没有;此能力在 Pro 层级没有对应物。租户上下文、API key 认证、配额检查器与计量同步适配器仅在 nextpdf/enterprise 包中提供。

API key 生成、校验和与时序安全验证在行为层面被描述。token 验证内部机制、key 哈希存储策略与计费提供方适配器内部机制不在公开面之内;计费提供方集成是一个接口,且是可替换的。

运营方负责 API key 仓库、计费提供方适配器实现、配额检查器与计量同步读取的权威用量来源,以及告警回调的去重。租户身份必须来源于运营方配置的经过认证的上下文(token、双向 TLS 或 API key)。NextPDF Enterprise 本身不持久化 key 或用量。

SaaS 面不适用任何出口管制限制。API key 与租户标识符可能是敏感信息;其存储范围与留存属于运营方的合规责任。本文档不是法律意见;请咨询你自己的合规与法律顾问。