You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PDFBox编写移除PDF只读模式与数字签名的等效代码

移除PDF写保护/加密及数字签名的PDFBox实现

我们时常需要移除PDF文档的写保护/加密以及数字签名,以便对文档进行修改并重新签名,比如原文档丢失或被修改导致数字签名损坏的场景。

此前我们使用iText 8实现了该功能,但要注意展平AcroForm并非最优方案,会导致交互式表单失效等问题,原代码如下:

public static byte[] cleanUpPdfItext(byte[] originalPdfData) throws Exception {
    // Read the PDF document
    try (
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            PdfReader pdfReader = new PdfReader(new ByteArrayInputStream(originalPdfData)).setUnethicalReading(true);
            PdfWriter pdfWriter = new PdfWriter(byteArrayOutputStream);
            PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter)
    ) {
        // Create the signature utils
        SignatureUtil signatureUtil = new SignatureUtil(pdfDocument);

        // Check if encrypted and/or contains signatures
        boolean isEncrypted = pdfReader.isEncrypted();
        boolean hasSignatures = !signatureUtil.getSignatureNames().isEmpty();

        // Handle all cases
        if (isEncrypted && hasSignatures) { // Encrypted and signatures
            // Remove the signatures
            PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDocument, true);
            form.flattenFields();

            // Write the changes to the output stream, so we can read them
            pdfDocument.close();

            // Get the manipulated document
            return byteArrayOutputStream.toByteArray();
        } else if (isEncrypted) { // Encrypted but no signatures
            // Write the changes to the output stream, so we can read them
            pdfDocument.close();

            // Get the manipulated document
            return byteArrayOutputStream.toByteArray();
        } else { // Not encrypted/no signatures
            // Return the original document data
            return originalPdfData;
        }
    }
}

现在需要编写等效的PDFBox代码,实现移除PDF的写保护/加密以及所有现有签名,使文档可编辑并重新签名。以下是补充完整后的代码:

public static byte[] cleanUpPdfbox(byte[] original) throws Exception {
    try (
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            PDDocument pdDocument = Loader.loadPDF(original)
    ) {
        // Check if encrypted or read only
        AccessPermission accessPermission = pdDocument.getCurrentAccessPermission();
        boolean isEncrypted = pdDocument.isEncrypted() || accessPermission.isReadOnly();

        // Check if signatures exist
        boolean hasSignatures = !pdDocument.getSignatureDictionaries().isEmpty();
        PDAcroForm pdAcroForm = pdDocument.getDocumentCatalog().getAcroForm();

        // Remove all security if required
        if (isEncrypted) {
            pdDocument.setAllSecurityToBeRemoved(true);
        }

        // Remove all signatures
        if (hasSignatures) {
            // 移除签名字典
            pdDocument.setSignatureDictionaries(null);
            
            if (pdAcroForm != null) {
                // 移除所有签名字段
                List<PDField> fieldsToRemove = new ArrayList<>();
                for (PDField field : pdAcroForm.getFields()) {
                    if (field instanceof PDSignatureField) {
                        fieldsToRemove.add(field);
                    }
                }
                fieldsToRemove.forEach(field -> pdAcroForm.getFields().remove(field));
                
                // 更新AcroForm字典,移除相关签名条目
                pdAcroForm.getCOSObject().removeItem(COSName.DS);
                pdAcroForm.getCOSObject().removeItem(COSName.SIG_FLAGS);
            }
            
            // 移除文档中的签名引用(如DSS字典)
            pdDocument.getDocumentCatalog().getCOSObject().removeItem(COSName.DSS);
        }

        // Write the document
        pdDocument.save(byteArrayOutputStream);
        return byteArrayOutputStream.toByteArray();
    }
}

代码说明:

  • 移除安全设置:通过setAllSecurityToBeRemoved(true)移除PDF的加密和只读限制,确保文档可编辑。
  • 移除签名字典:直接清空文档的签名字典集合,清除已有的签名记录。
  • 清理签名字段:遍历AcroForm中的字段,移除所有PDSignatureField类型的字段,并清理AcroForm字典中与签名相关的条目(如DS、SIG_FLAGS)。
  • 移除DSS字典:如果文档存在文档安全存储(DSS)字典,也一并移除,避免残留签名相关数据。

内容的提问来源于stack exchange,提问作者swaechter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 12:34:52