PII 遮蔽與個資合規¶
PHP Compatibility
This example uses PHP 8.5 syntax. If your environment runs PHP 8.1 or 7.4, use NextPDF Backport for a backward-compatible build.
個人識別資訊(PII,Personally Identifiable Information)遮蔽是 GDPR(EU 2016/679)、台灣個人資料保護法(個資法)及各行業合規框架的核心要求。NextPDF Pro 的遮蔽機制在排版時期攔截敏感文字,確保敏感資料永遠不會進入:
- PDF 內容串流(content stream)
- 字型子集(font subset)
- ToUnicode CMap(字型反查表)
- 文件詮釋資料(XMP metadata)
- 書籤文字或注釋
架構:TextPreprocessor 管線¶
PII 遮蔽整合於 Core 的 TextPreprocessorInterface 介面。RedactionTextPreprocessor 在文字進入排版引擎之前攔截並轉換:
graph LR
Input["原始文字\n(含 PII)"] --> Preprocessor["RedactionTextPreprocessor\n(排版時期攔截)"]
Preprocessor --> Detector["PiiDetector\n(規則/RegEx/ML)"]
Detector --> Redactor["PiiRedactor\n(替換/遮蔽/雜湊)"]
Redactor --> Layout["排版引擎\n(乾淨文字)"]
Layout --> Stream["PDF 內容串流\n(永不含原始 PII)"]
Preprocessor --> AuditLog["合規審計日誌\n(遮蔽操作記錄)"]
style Stream fill:#16a34a,color:#fff
style AuditLog fill:#D97706,color:#fff 快速開始¶
use NextPDF\Pro\Redaction\RedactionTextPreprocessor;
use NextPDF\Pro\Redaction\Detector\RegexPiiDetector;
use NextPDF\Pro\Redaction\Redactor\MaskRedactor;
use NextPDF\Pro\Redaction\Redactor\HashRedactor;
use NextPDF\Pro\Redaction\PiiCategory;
use NextPDF\Pro\Redaction\Audit\RedactionAuditLogger;
use NextPDF\Pro\Document\ProDocument;
// 1. 設定偵測規則
$detector = RegexPiiDetector::withBuiltinRules(
categories: [
PiiCategory::TaiwanNationalId, // 台灣身分證字號 A123456789
PiiCategory::TaiwanUniformNumber, // 統一編號
PiiCategory::EmailAddress, // 電子郵件
PiiCategory::PhoneNumber, // 電話號碼(支援多國格式)
PiiCategory::CreditCard, // 信用卡號(Luhn 驗證)
PiiCategory::BankAccount, // 銀行帳號
PiiCategory::IpAddress, // IP 位址
],
);
// 可加入自訂正規表達式規則
$detector->addCustomRule(
name: 'employee-id',
pattern: '/EMP-\d{6}/',
category: PiiCategory::Custom,
);
// 2. 設定遮蔽策略
$redactor = MaskRedactor::create(
maskChar: '█', // 遮蔽字元
preserveLength: true, // 保留原始長度(維持排版)
preservePrefix: 3, // 保留前 N 個字元(如身分證前段 A12█████)
);
// 3. 設定審計日誌
$auditLogger = new RedactionAuditLogger(
logPath: '/var/log/nextpdf/redaction.jsonl',
includePosition: true, // 記錄頁碼與位置
includeCategory: true, // 記錄 PII 類型(不記錄原始值)
);
// 4. 建立 TextPreprocessor
$preprocessor = new RedactionTextPreprocessor(
detector: $detector,
redactor: $redactor,
auditLogger: $auditLogger,
);
// 5. 注入至 ProDocument
$doc = ProDocument::createStandalone(
textPreprocessors: [$preprocessor],
);
// 6. 正常生成文件——PII 自動遮蔽
$doc->addPage();
$doc->text('客戶姓名:王大明', x: 20, y: 30);
$doc->text('身分證號:A123456789', x: 20, y: 45); // 自動遮蔽為 A12█████
$doc->text('Email:[email protected]', x: 20, y: 60); // 自動遮蔽
$doc->text('信用卡:4111-1111-1111-1111', x: 20, y: 75); // 自動遮蔽
$pdf = $doc->render();
// 輸出的 PDF 中,上述 PII 已在串流層級完全遮蔽
遮蔽策略選項¶
MaskRedactor — 字元替換¶
use NextPDF\Pro\Redaction\Redactor\MaskRedactor;
// 完全遮蔽
$redactor = MaskRedactor::create(maskChar: '█');
// 保留部分資訊(常見於客服場景)
$redactor = MaskRedactor::create(
maskChar: '*',
preservePrefix: 3, // 前 3 字元可見
preserveSuffix: 4, // 後 4 字元可見(適合信用卡末 4 碼)
preserveLength: true,
);
HashRedactor — 不可逆雜湊¶
use NextPDF\Pro\Redaction\Redactor\HashRedactor;
// 以 SHA-256 雜湊取代原始值(可用於追蹤但不可還原)
$redactor = HashRedactor::create(
algorithm: 'sha256',
salt: (string) getenv('REDACTION_HASH_SALT'), // 必填:防止彩虹表攻擊
outputLength: 8, // 截取前 8 個字元
prefix: '[HASH:',
suffix: ']',
);
// 輸出範例:[HASH:a3f8c91b]
TokenRedactor — 可逆代換¶
use NextPDF\Pro\Redaction\Redactor\TokenRedactor;
use NextPDF\Pro\Redaction\Token\DatabaseTokenStore;
// 將 PII 替換為隨機 Token,Token 對應關係安全儲存於外部
$tokenStore = new DatabaseTokenStore(pdo: $pdo, tableName: 'pii_tokens');
$redactor = TokenRedactor::create(
tokenStore: $tokenStore,
tokenPrefix: 'PII-',
tokenLength: 16,
);
// 輸出範例:PII-4f8a9b2c1e3d7f6a
// 授權使用者可透過 tokenStore 還原原始值
複合遮蔽管線¶
單一文件可串接多個 Preprocessor,依優先序執行:
use NextPDF\Pro\Redaction\RedactionTextPreprocessor;
use NextPDF\Pro\Redaction\Detector\CompositeDetector;
// 組合多個偵測器
$compositeDetector = new CompositeDetector([
RegexPiiDetector::withBuiltinRules([PiiCategory::TaiwanNationalId, PiiCategory::CreditCard]),
NlpPiiDetector::forLanguage('zh-Hant'), // NLP 偵測(需安裝額外模型)
CustomRuleDetector::fromYaml('/config/pii-rules.yaml'),
]);
$preprocessor = new RedactionTextPreprocessor(
detector: $compositeDetector,
redactor: MaskRedactor::create(maskChar: '█'),
auditLogger: $auditLogger,
);
批次遮蔽既有 PDF¶
除在生成時遮蔽外,Pro 也支援對既有 PDF 執行後處理遮蔽:
use NextPDF\Pro\Redaction\PdfRedactionProcessor;
use NextPDF\Pro\Redaction\RedactionReport;
$processor = new PdfRedactionProcessor(
detector: $detector,
redactor: $redactor,
auditLogger: $auditLogger,
);
$inputPdf = file_get_contents('/uploads/contract.pdf');
/** @var RedactionReport $report */
$report = $processor->process(
pdfBytes: $inputPdf,
options: RedactionProcessorOptions::create(
redactContent: true, // 遮蔽頁面內容
redactMetadata: true, // 清除 XMP 詮釋資料中的 PII
redactAnnotations: true, // 遮蔽注釋文字
redactBookmarks: true, // 遮蔽書籤標題
flattenForms: false, // 保留表單欄位結構
),
);
$redactedPdf = $report->getRedactedPdf();
$summary = $report->getSummary(); // RedactionSummary: 遮蔽數量、類型分布
file_put_contents('/output/redacted-contract.pdf', $redactedPdf);
echo sprintf(
'Redacted %d PII instances across %d pages. Categories: %s',
$summary->getTotalRedacted(),
$summary->getAffectedPageCount(),
implode(', ', $summary->getCategoryBreakdown()),
);
合規審計日誌格式¶
每次遮蔽操作均產生 JSONL 格式的審計記錄(僅記錄操作事實,不記錄原始 PII 值):
{
"timestamp": "2026-03-04T10:23:45+08:00",
"document_id": "doc-7f3a9b2c",
"page": 1,
"position": {"x": 20.0, "y": 45.0},
"pii_category": "TaiwanNationalId",
"redaction_strategy": "mask",
"original_length": 10,
"redacted_value": "A12█████",
"rule_matched": "tw-national-id-builtin",
"operator": "system"
}
PDPA(台灣個資法)合規要點¶
| 個資法條文 | 要求 | NextPDF Pro 對應功能 |
|---|---|---|
| 第 11 條 | 個資正確性,有錯誤應更正 | TokenRedactor 支援可逆遮蔽 |
| 第 19 條 | 特定目的外不得蒐集利用 | PiiCategory 精確分類控制 |
| 第 27 條 | 安全維護措施義務 | 審計日誌 + 串流層級遮蔽 |
| 第 28 條 | 損害賠償責任 | 完整操作記錄作為舉證依據 |