iText7 如何实现PDF签名完成后修改签名外观
iText7 签名后更新签名外观实现方案
首先明确核心前提:PDF签名完成后修改外观不能破坏签名有效性,必须符合ISO 32000签名规范要求,仅通过增量更新修改签名域的外观层,不能改动签名覆盖的字节范围,该逻辑和你之前用iTextSharp实现的底层逻辑一致,只是iText7的API做了重构调整。
核心实现步骤
1. 签名阶段配置(必须做的前置配置)
签名时需要预留修改权限,否则后续修改会被判定为签名篡改:
- 签名时认证级别设置为
PdfSigner.NOT_CERTIFIED,禁止使用CERTIFIED_NO_CHANGES_ALLOWED等级 - 确认签名域名称,后续更新外观需要通过名称定位签名域
签名阶段示例代码
// 初始化签名器 PdfReader reader = new PdfReader("待签名原文档.pdf"); PdfSigner signer = new PdfSigner(reader, new FileOutputStream("已签名文档.pdf"), new StampingProperties()); // 设置签名域名称,可自定义 signer.setFieldName("contract_sign_001"); // 配置可修改权限 signer.setCertificationLevel(PdfSigner.NOT_CERTIFIED); // 配置签名位置、初始占位外观 PdfSignatureAppearance appearance = signer.getSignatureAppearance(); appearance.setPageRect(new Rectangle(100, 600, 200, 100)); appearance.setPageNumber(1); // 可设置占位文本,也可以留空 appearance.setLayer2Text("签名中..."); // 执行签名(替换为你自己的私钥、证书、摘要算法配置即可) IExternalSignature signImpl = new PrivateKeySignature(你的私钥对象, DigestAlgorithms.SHA256, "BC"); signer.signDetached(new BouncyCastleDigest(), signImpl, 你的证书链数组, null, null, null, 0, PdfSigner.CryptoStandard.CMS);
2. 签名后更新外观步骤
必须使用增量更新模式打开PDF,否则会重写整个文档破坏签名有效性:
更新外观示例代码
// 增量模式打开已签名PDF,useAppendMode是核心配置 PdfReader signedReader = new PdfReader("已签名文档.pdf"); PdfWriter outWriter = new PdfWriter("替换外观后最终文档.pdf"); PdfDocument pdfDoc = new PdfDocument(signedReader, outWriter, new StampingProperties().useAppendMode()); // 定位目标签名域 SignatureUtil signUtil = new SignatureUtil(pdfDoc); PdfSignatureFormField sigField = signUtil.getSignatureField("contract_sign_001"); Rectangle sigArea = sigField.getWidgets().get(0).getRectangle().toRectangle(); // 绘制自定义新外观 PdfFormXObject newAppearance = new PdfFormXObject(sigArea); Canvas canvas = new Canvas(newAppearance, pdfDoc); // 以下可自定义绘制任意内容:文本、图片、图形等 canvas.add(new Paragraph("张三 2024-05-20 已签署").setFontSize(12).setMarginLeft(10)); Image sealImg = new Image(ImageDataFactory.create("你的电子印章路径.png")); sealImg.scaleToFit(80, 80).setFixedPosition(10, 10); canvas.add(sealImg); canvas.close(); // 替换签名域默认外观 sigField.setAppearance(PdfName.N, new PdfAppearance(newAppearance.getPdfObject())); // 保存文档 pdfDoc.close();
和iTextSharp的核心API差异
- 原有
AcroFields类的签名相关能力拆分到SignatureUtil工具类、PdfSignatureFormField签名域类中 - 外观绘制统一使用
CanvasAPI替代原有直接操作PdfContentByte的逻辑 - 增量更新配置改由
StampingProperties.useAppendMode()设置,不再通过PdfStamper的构造参数配置
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

