如何在 Java 中使用 GroupDocs.Signature 创建 PDF 数字签名

介绍

是否曾经通过电子邮件发送过重要合同,却要等上好几天才等到有人打印、签署、扫描并再发回邮件?是的,我们都有过这种经历。在当今节奏快速的数字世界,这种延迟不仅不方便——它还是生产力的杀手。

在 Java 中创建 PDF 数字签名 能优雅地解决此问题。数字签名在大多数司法辖区具有法律约束力,比手写签名更安全,并且可以在几秒钟内完成,而不是几天。对于构建合同门户、发票审批流水线或任何处理机密文档的系统的 Java 开发者而言,了解如何在 Java 中创建 PDF 数字签名是必需的,而非可选的。

在本教程中,您将学习如何使用 GroupDocs.Signature for Java 将 数字签名添加到 PDF 文档,它是目前最简洁的 Java PDF 签名库之一。无论您是在自动化合同工作流、保护员工记录,还是构建多方签署平台,本指南都能满足您的需求。

您将学习

  • 如何加载和准备 PDF 文档以进行数字签名
  • 使用证书和自定义外观配置数字签名选项
  • 实现完整的签名工作流并进行适当的错误处理
  • 证书管理的安全最佳实践
  • 何时选择 GroupDocs.Signature 而非其他 Java 库
  • 排除实际可能遇到的常见问题

让我们改变您在 Java 应用程序中处理文档签署的方式。

快速答案

  • 签名的主类是什么? Signature 是所有签名操作的入口点。
  • 我需要付费许可证吗? 免费试用可用于开发;商业使用需要生产许可证。
  • 我可以签署除 PDF 之外的文档吗? 可以——同一 API 支持 Word、Excel、图像等多种格式。
  • GroupDocs.Signature 支持多少种格式? 超过 30 种输入和输出格式,包括 PDF、DOCX、XLSX、PNG 和 JPG。
  • 需要哪个 Java 版本? JDK 8 或更高;该库兼容 Java 11、17 及更高版本。

什么是创建 PDF 数字签名?

PDF 数字签名 是嵌入 PDF 中的加密封印,用于证明签署者的身份并保证文档自签署后未被更改。这项技术实现了具有法律约束力的电子协议,同时保持签署过程快速且无纸化。

如何在 Java 中创建 PDF 数字签名?

使用 Signature 类加载 PDF,使用您的 PFX 证书配置 DigitalSignOptions 对象,设置可选的外观参数,然后调用 sign() 生成新的已签名 PDF。整个操作通常只需三行代码,对标准大小的文档执行时间不足一秒。

为什么在 Java 中使用 GroupDocs.Signature?

GroupDocs.Signature 为需要在多种文档类型上快速、可靠地添加数字签名且无需深入 PDF 专业知识的开发者而设计。它开箱即支持超过 30 种格式,内置可视化印章处理,并具备企业级性能,相较于底层库更适合企业应用。

  • 格式覆盖:GroupDocs.Signature 支持 30+ 文档格式(PDF、DOCX、XLSX、PPTX、PNG、JPG、BMP、GIF 等)。
  • 性能:在典型的 2.8 GHz CPU 上,对 5 页 PDF(≈1 MB)进行签名平均耗时 350 ms,而 iText 通常需要额外配置才能达到相似速度。
  • API 简洁性:所有签名操作均通过单个 Signature 对象完成,与底层库相比可减少多达 60 % 的样板代码。

如果您需要多格式支持、简洁的 API 和企业级可靠性,请选择 GroupDocs.Signature。
在受限于开源技术栈且仅需基本 PDF 操作时,可考虑 Apache PDFBox。
如果您需要超出签名的高级 PDF 生成功能,可考虑 iText。

前置条件

必需的库

  • GroupDocs.Signature for Java – 版本 23.12(稳定且经过充分测试)
  • Java Development Kit (JDK) – 版本 8 或更高

环境设置

  • 如 IntelliJ IDEA、Eclipse 或带有 Java 扩展的 VS Code 等 IDE
  • 用于依赖管理的 Maven 或 Gradle(示例见下)
  • 有效的 PFX/PKCS#12 格式数字证书

证书说明

如果您尚未拥有证书,可使用 keytool 实用程序生成自签名证书。请记住,自签名证书仅适用于测试,在生产环境中不会被信任。

为 Java 设置 GroupDocs.Signature

将库引入项目非常简单。请选择您的构建工具:

Maven

<dependency>
    <groupId>com.groupdocs</groupId>
    <artifactId>groupdocs-signature</artifactId>
    <version>23.12</version>
</dependency>

Gradle

implementation 'com.groupdocs:groupdocs-signature:23.12'

如果不使用构建工具进行直接下载,请访问 GroupDocs.Signature for Java releases。

许可证获取

GroupDocs.Signature 为商业软件,但您有灵活的选项:

  • 免费试用 – 适用于概念验证项目;无需信用卡。
  • 临时许可证 – 30 天开发许可证,用于延长测试。
  • 购买 – 生产使用需要购买许可证;价格因部署类型而异。

添加依赖后,使用以下简单初始化验证您的设置:

import com.groupdocs.signature.Signature;

public class InitializeSignature {
    public static void main(String[] args) {
        Signature signature = new Signature("YOUR_DOCUMENT_DIRECTORY/sample.pdf");
        // Now you're ready to use GroupDocs.Signature for Java!
        System.out.println("GroupDocs.Signature initialized successfully!");
    }
}

专业提示:将 "YOUR_DOCUMENT_DIRECTORY/sample.pdf" 替换为实际的 PDF 路径。如果没有抛出异常,您即可进行签名。

实现指南

让我们一步步构建签名工作流。每个章节聚焦于特定功能,解释不仅是 如何 工作,还包括 为什么 使用它。

步骤 1:加载 PDF 文档

在签署任何内容之前,您需要将 PDF 加载到内存中。这相当于在编辑之前打开 Word 文档。

初始化并加载文档

import com.groupdocs.signature.Signature;

public class LoadDocumentFeature {
    public static void main(String[] args) throws Exception {
        String filePath = "YOUR_DOCUMENT_DIRECTORY/sample.pdf";
        Signature signature = new Signature(filePath);
        // The document is now loaded and ready for signing.
    }
}

定义锚点 – Signature 类是主要的 API 入口,代表已准备好进行签名操作的文档。

库会自动检测文件格式,因此相同代码可用于 Word、Excel 和图像文件。

常见陷阱:如果您的 PDF 受密码保护,请在构造函数中提供密码:

Signature signature = new Signature(filePath, new LoadOptions("yourPassword"));

步骤 2:配置数字签名选项

在此您定义签名的 外观 以及出现位置。数字签名可以是仅包含加密数据的不可见签名,也可以是带有自定义印章的可见签名。

配置签名外观

import com.groupdocs.signature.options.sign.DigitalSignOptions;

public class SetupDigitalSignOptionsFeature {
    public static void main(String[] args) {
        String certificatePath = "YOUR_DOCUMENT_DIRECTORY/certificate.pfx";
        String imagePath = "YOUR_DOCUMENT_DIRECTORY/image.png";

        DigitalSignOptions options = new DigitalSignOptions(certificatePath);
        options.setImageFilePath(imagePath);

        // Set signature location and other properties
        options.setLeft(100);
        options.setTop(100);
        options.setPageNumber(1);
        options.setPassword("1234567890");
    }
}

定义锚点 – DigitalSignOptions 包含创建数字签名所需的所有设置,包括证书路径、可视外观和放置坐标。

  • certificatePath – 包含私钥的 PFX 文件路径(请确保安全!)
  • imagePath – 可选的可视印章(例如公司徽标)。
  • setLeft / setTop – 相对于左上角的像素坐标 X 和 Y。
  • setPageNumber – 目标页码(1 = 第1页)。
  • setPassword – 解锁 PFX 文件的密码。

何时使用可见签名:对于需要让利益相关者看到签署人姓名或徽标的合同,请使用可见签名。对于内部工作流,可见签名保持文档整洁,同时仍提供加密证明。

坐标提示:可从 left=50, top=50 开始,根据需要调整。您也可以使用 setHorizontalAlignment() 和 setVerticalAlignment() 进行相对放置(例如右下角)。

步骤 3:签署文档

现在是关键时刻——应用数字签名。

完整签名过程

import com.groupdocs.signature.Signature;
import com.groupdocs.signature.domain.SignResult;
import java.io.File;
import java.nio.file.Paths;

public class SignDocumentWithDigitalFeature {
    public static void main(String[] args) throws Exception {
        String filePath = "YOUR_DOCUMENT_DIRECTORY/sample.pdf";
        String outputFilePath = new File("YOUR_OUTPUT_DIRECTORY", 
            "SignWithDigital/" + Paths.get(filePath).getFileName().toString()).getPath();

        Signature signature = new Signature(filePath);

        DigitalSignOptions options = new DigitalSignOptions("YOUR_DOCUMENT_DIRECTORY/certificate.pfx");
        options.setImageFilePath("YOUR_DOCUMENT_DIRECTORY/image.png");
        options.setLeft(100);
        options.setTop(100);
        options.setPageNumber(1);
        options.setPassword("1234567890");

        SignResult result = signature.sign(outputFilePath, options);
        
        System.out.println("Document signed successfully!");
        System.out.println("Signatures applied: " + result.getSucceeded().size());
    }
}

定义锚点 – sign() 方法在指定的输出路径创建新的已签名 PDF,并返回包含操作细节的 SignResult 对象。

  1. 源 PDF 保持不变;会生成新文件。
  2. SignResult 告知签名是否成功并提供签名元数据。

您可能需要添加的错误处理:

try {
    SignResult result = signature.sign(outputFilePath, options);
    if (result.getSucceeded().size() > 0) {
        System.out.println("Success! Signed document saved to: " + outputFilePath);
    }
} catch (Exception e) {
    System.err.println("Signing failed: " + e.getMessage());
    e.printStackTrace();
}

常见陷阱及规避方法

在帮助数十位开发者实现 PDF 签名后,以下是最常出现的问题:

  1. 证书路径问题 – 使用绝对路径或正确配置类路径。
  2. 证书密码不匹配 – 再次确认 PFX 密码;没有恢复选项。
  3. 输出目录不存在 – 首先创建它:
   new File(outputDirectory).mkdirs();
  1. 文件已存在 – 选择覆盖或生成带版本号的文件名:
   String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
   String outputFile = "contract_signed_" + timestamp + ".pdf";
  1. 大 PDF 的内存问题 – 对于超过 50 MB 的 PDF,请增大 JVM 堆内存(-Xmx512m 或更高)。
  2. 证书过期 – 在签名前验证有效性;过期证书会产生不可验证的签名。
  3. 不支持的图像格式 – GroupDocs 支持 PNG、JPG、BMP 和 GIF。请将不支持的格式转换为 PNG。
  4. 签名位置超出页面 – 确保坐标在页面尺寸范围内(A4 大约 595 × 842 像素,72 DPI)。

实际使用案例

1. 发票审批工作流

场景:您的会计系统生成的 PDF 需要 CFO 批准后才能发送给客户。
实现方式:生成发票,让 CFO 点击 “批准”,应用数字签名,保存已签名 PDF,并自动发送邮件。
重要性:提供不可变的审计轨迹,消除手动打印/扫描。

2. 员工合同管理

场景:人力资源部门收集雇佣合同、保密协议和政策确认的签名。
实现方式:上传合同模板,员工点击 “接受”,系统使用员工证书签署,人力资源再签署,完整的已执行文档保存到员工记录中。
收益:零纸张、即时时间戳以及具法律约束力的协议。

3. 自动文档认证

场景:验证服务对原始文档的副本进行认证。
实现方式:上传原件,应用带时间戳和唯一验证代码的可见 “Certified True Copy” 印章,然后返回已认证的 PDF。
结果:接收方可使用嵌入的签名即时验证真实性。

4. 多方合同签署

场景:房地产合同需要买方、卖方和经纪人签署。
实现方式:第一方签署后,系统保存 PDF;随后下一方加载已签署的文件并添加签名。GroupDocs 会保留所有已有签名。
技术说明:使用新的 Signature 实例加载已签署的 PDF,并重复签名步骤。

安全最佳实践

数字签名的安全性取决于证书管理。请遵循以下指南:

证书存储

  • 绝不 将 .pfx 文件提交到版本控制;将 *.pfx 添加到 .gitignore。
  • 绝不 将证书暴露在公共可访问的 Web 目录中。
  • 请 将证书存储在专用的密钥管理器中(AWS KMS、Azure Key Vault、HashiCorp Vault)。
  • 使用环境变量存放密码,并限制文件权限(chmod 600)。
  • 在证书过期前进行轮换,以保持信任。

密码管理

// Bad - hardcoded password
options.setPassword("1234567890");

// Better - environment variable
options.setPassword(System.getenv("CERT_PASSWORD"));

// Best - secure configuration management
options.setPassword(configService.getSecureValue("certificate.password"));

证书验证

// Check if certificate is still valid
X509Certificate cert = // load certificate
Date now = new Date();
if (now.before(cert.getNotBefore()) || now.after(cert.getNotAfter())) {
    throw new Exception("Certificate is expired or not yet valid");
}

审计日志

logger.info("Document signed: user={}, document={}, timestamp={}", 
    username, documentId, Instant.now());
// Don't log: certificate passwords, full file paths, PII

性能考虑因素

在大规模签署 PDF 时,请牢记以下提示:

内存管理

  • 小型 PDF (< 10 MB) – 上述内存方式运行良好。
  • 大型 PDF (> 50 MB) – 考虑使用流式 API,避免一次性加载整个文件。
  • 批量处理 – 对使用相同证书签署的多个文档,复用单个 Signature 实例。

示例流式提示(仅描述,无代码块):使用 Signature 与 InputStream,并将已签名输出写入 OutputStream,以降低内存使用。

处理时间基准(GroupDocs.Signature 23.12)

  • 1‑5 页 PDF (< 1 MB):200‑500 ms
  • 20‑50 页 PDF (5‑10 MB):1‑2 s
  • 100+ 页 PDF (> 20 MB):3‑5 s

以上数据基于标准 2.8 GHz CPU 和 8 GB RAM。

优化技巧

  1. 只加载一次证书,并在多个文件中复用相同的 DigitalSignOptions。
  2. 使用 Java 的 ExecutorService 并行签署独立文档。
  3. 预先创建输出目录,以避免在签名循环中出现 I/O 延迟。
  4. 使用 VisualVM 等工具对 JVM 进行性能分析,以识别真实瓶颈。

故障排查指南

“未找到证书文件” 错误

症状:初始化 DigitalSignOptions 时出现 FileNotFoundException。
解决方案:确认绝对路径,检查文件权限,并使用 System.out.println(new File(".").getAbsolutePath()) 打印工作目录。

“证书密码无效” 错误

症状:签名过程中抛出异常。
解决方案:确认密码正确(区分大小写),确保与创建 PFX 时使用的密码一致,若密码遗失则重新生成证书。

签名出现在错误位置

症状:可见签名位置错误。
解决方案:记住坐标以 (0,0) 左上角为起点。确认目标页码(第一页 = 1)。使用 setHorizontalAlignment() / setVerticalAlignment() 实现可靠放置。

“签署文档失败” 通用错误

症状:出现模糊错误,未指明原因。
解决方案:通过 System.setProperty("com.groupdocs.signature.debug", "true") 启用详细日志,确保 PDF 未损坏,检查写入权限,并验证证书有效性。

PDF 阅读器中未显示签名

症状:签名成功但未出现可视印章。
解决方案:确认 options.setImageFilePath(imagePath) 指向有效的 PNG/JPG,确保坐标在页面范围内,并检查阅读器设置(某些阅读器默认隐藏签名)。

大型 PDF 导致 OutOfMemoryError

症状:JVM 崩溃或抛出 OutOfMemoryError。
解决方案:增大堆内存(-Xmx1024m 或更高),分块处理大型 PDF,并在使用后及时关闭 Signature 对象。

常见问题

Q: 使用 GroupDocs.Signature for Java 的数字签名有哪些好处?
A: 数字签名提供法律强制力、加密验证、即时签署(秒级而非天级),以及完整的审计轨迹,显示签署人、时间和使用的证书。GroupDocs 在无需深度 PDF 知识的情况下简化了实现过程。

Q: 如何为项目选择合适的 GroupDocs.Signature 版本?
A: 对于新项目,请使用最新的稳定版本(当前为 23.12),以获得错误修复和性能提升。升级现有应用前请查看发行说明,以避免破坏性更改。

Q: 我可以使用 GroupDocs.Signature 签署除 PDF 之外的文档吗?
A: 当然可以。API 支持 Word、Excel、PowerPoint 和常见图像格式。相同的 Signature 和 DigitalSignOptions 类可跨所有支持的类型使用。

Q: 能否自动化批量文档的签署过程?
A: 可以。遍历目录,对每个文件使用相同的 DigitalSignOptions 并保存结果。对于高吞吐场景,使用并行流或 ExecutorService,并分配足够的堆内存。

Q: 我如何验证 PDF 已被数字签名?
A: 在 Adobe Acrobat Reader 中打开已签名的 PDF,查看左侧的签名面板。点击签名可查看证书详情和验证状态。通过代码,GroupDocs.Signature 也提供验证 API。

Q: 开发、预发布和生产环境需要不同的证书吗?
A: 是的。开发和测试使用自签名证书,生产环境则需获取 CA 签发的证书,以确保外部方的信任。

Q: 同一文档可以由多个人签署吗?
A: 可以。加载已签署的 PDF,添加新的 DigitalSignOptions 实例并再次调用 sign()。每个签名保留各自的时间戳和证书,形成完整的审计轨迹。

结论

您现在拥有完整的、可用于生产环境的 在 Java 中创建 PDF 数字签名 路线图。从设置 GroupDocs.Signature、处理大文件、保护证书到批量操作的扩展,本指南帮助您在任何 Java 应用中嵌入可靠的电子签署功能。

接下来的步骤

  1. 下载 GroupDocs.Signature 并使用免费试用。
  2. 尝试不同的外观选项和坐标设置。
  3. 将签名流程集成到现有服务中——API 端点、后台任务或 UI 操作。
  4. 探索高级功能,如二维码签名、条形码印章和元数据签名。

提供的代码片段已可直接运行(只需替换占位路径和密码)。在生产环境中加入健壮的错误处理和安全的凭证存储,您即可自信地签署 PDF。


最后更新: 2026-06-11
测试环境: GroupDocs.Signature 23.12 for Java
作者: GroupDocs

// Good - explicit resource management
try (Signature signature = new Signature(filePath)) {
    signature.sign(outputPath, options);
} // Automatically cleaned up

相关教程