PDFBox设置签名锁后仍可添加有效签名如何解决
PDFBox认证签名锁定后新增签名原签名仍有效问题
问题描述
可参考我此前提出的关于签名锁定后禁止新增其他审批/签名的相关问题。
我目前已成功实现文档认证加锁功能,但测试发现锁定后仍可对文档执行签名操作、新增其他签名或审批内容,且操作后原有签名仍显示为有效状态,不符合预期:
完成签名锁定后,若有其他主体对文档进行签名,原有签名应变为无效状态。

当前文档版本流转路径为:rev 1 -> rev 2 -> 认证 -> 锁定 -> 新增rev 4(新增后签名仍为有效状态)
现有实现代码
// 创建空签名字段 PDDocument docEx=PDDocument.load(inputFile); PDAcroForm acroFormField = docEx.getDocumentCatalog().getAcroForm(); acroFormField.getCOSObject().setNeedToBeUpdated(true); COSObject fields = acroFormField.getCOSObject().getCOSObject(COSName.FIELDS); if (fields != null) fields.setNeedToBeUpdated(true); acroFormField.setSignaturesExist(true); acroFormField.setAppendOnly(true); acroFormField.getCOSObject().setDirect(true); PDPage pageField = docEx.getPage(page); // 创建空签名字段,默认名称为"Signature1" PDSignatureField signatureField = new PDSignatureField(acroFormField); PDAnnotationWidget widget = signatureField.getWidgets().get(0); PDRectangle rectField = new PDRectangle((float)humanRect.getX(), (float)humanRect.getY(), (float)humanRect.getWidth(), (float)humanRect.getHeight()); widget.setRectangle(rectField); widget.getCOSObject().setNeedToBeUpdated(true); widget.setPage(pageField); pageField.getAnnotations().add(widget); pageField.getCOSObject().setNeedToBeUpdated(true); acroFormField.getFields().add(signatureField); setLock(signatureField, acroFormField); docEx.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true); docEx.saveIncremental(fos); fos.close(); // 关闭文档,替换为已创建空签名字段的文件 PDDocument doc = PDDocument.load(signedFile); FileOutputStream fosSeal = new FileOutputStream(signedFile); PDSignature signatureLock = new PDSignature(); PDSignatureField signatureFieldLoad = (PDSignatureField) doc.getDocumentCatalog().getAcroForm().getField("Signature1"); LogSystem.info("signatureFieldLoad " + signatureFieldLoad.getValueAsString()); LogSystem.info("signaturelock " + signatureLock); signatureFieldLoad.setValue(signatureLock); COSBase lock = signatureFieldLoad.getCOSObject().getDictionaryObject(COS_NAME_LOCK); if (lock instanceof COSDictionary) { COSDictionary lockDict = new COSDictionary(); lockDict.setItem(COS_NAME_ACTION, COS_NAME_ALL); lockDict.setItem(COSName.TYPE, COS_NAME_SIG_FIELD_LOCK); COSDictionary transformParams = new COSDictionary(lockDict); transformParams.setItem(COSName.TYPE, COSName.getPDFName("TransformParams")); transformParams.setItem(COSName.V, COSName.getPDFName("1.2")); transformParams.setInt(COSName.P, 1); transformParams.setDirect(true); transformParams.setNeedToBeUpdated(true); COSDictionary sigRef = new COSDictionary(); sigRef.setItem(COSName.TYPE, COSName.getPDFName("SigRef")); sigRef.setItem(COSName.getPDFName("TransformParams"), transformParams); sigRef.setItem(COSName.getPDFName("TransformMethod"), COSName.getPDFName("FieldMDP")); sigRef.setItem(COSName.getPDFName("Data"), doc.getDocumentCatalog()); sigRef.setDirect(true); COSArray referenceArray = new COSArray(); referenceArray.add(sigRef); signatureLock.getCOSObject().setItem(COSName.getPDFName("Reference"), referenceArray); LogSystem.info("LOCK DICTIONARY"); final Predicate<PDField> shallBeLocked; final COSArray fieldsLock = lockDict.getCOSArray(COSName.FIELDS); final List<String> fieldNames = fieldsLock == null ? Collections.emptyList() : fieldsLock.toList().stream().filter(c -> (c instanceof COSString)).map(s -> ((COSString)s).getString()).collect(Collectors.toList()); final COSName action = lockDict.getCOSName(COSName.getPDFName("Action")); if (action.equals(COSName.getPDFName("Include"))) { shallBeLocked = f -> fieldNames.contains(f.getFullyQualifiedName()); } else if (action.equals(COSName.getPDFName("Exclude"))) { shallBeLocked = f -> !fieldNames.contains(f.getFullyQualifiedName()); } else if (action.equals(COSName.getPDFName("All"))) { shallBeLocked = f -> true; } else { // 未知操作,不锁定任何字段 shallBeLocked = f -> false; } lockFields(doc.getDocumentCatalog().getAcroForm().getFields(), shallBeLocked); setMDPPermission(doc, signatureLock, 2); // 默认过滤器 signatureLock.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); // 基础签名和PAdES第2部分签名的子过滤器 signatureLock.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED); signatureLock.setName(name); // 签名日期,有效签名必填项 signatureLock.setSignDate(getDate()); // 若使用外部签名,不设置SignatureInterface实例 SignatureInterface signatureInterface = isExternalSigning() ? null : this; doc.addSignature(signatureLock, signatureInterface, signatureOptions); doc.getDocumentCatalog().getAcroForm().getField("Signature1").setPartialName(SignatureField); if (isExternalSigning()) { this.tsaUrl=tsaUrl; ExternalSigningSupport externalSigning = doc.saveIncrementalForExternalSigning(fosSeal); // 调用外部签名服务 byte[] cmsSignature =IOUtils.toByteArray(externalSigning.getContent()); String sgn=null; try { sgn = signingProcess(cmsSignature); }catch(Exception e) { LogSystem.error(e.toString()); e.printStackTrace(); doc.close(); Telegram tele = new Telegram(); tele.Send(e.toString()); return false; } // 写入服务返回的签名字节 if (sgn != null) { externalSigning.setSignature(attachSignature(sgn)); } }
咨询问题
- 该问题应如何排查修正?
- 如何正确配置才能实现禁止文档修改、签名锁定后新增签名则原签名失效的效果?
内容的提问来源于stack exchange,提问作者blinkbink
相关产品推荐
相关产品推荐

