You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用iTextSharp存储数字签名至数据库及在Handler中读取PDF签名数据

如何在Handler中读取PDF数字签名数据

这个问题我之前帮别人排查过,核心原因是PDF的数字签名并不是普通的表单键值对——它是嵌入到PDF文档结构中的加密数据,没法通过HttpContext的常规表单集合直接获取。下面给你一套可行的解决方案:

关键前提:提交完整的带签名PDF

首先要调整你的表单提交逻辑:不能只提交表单字段,必须把用户签名后的完整PDF文件作为文件上传到Handler。因为数字签名是和PDF文档绑定的,脱离了PDF的签名数据没有意义,也无法被正确解析。

  • 修改表单的enctype属性为multipart/form-data,确保支持文件上传
  • 在PDF表单的提交流程中,让浏览器将签名后的PDF作为文件附件提交(可以通过JavaScript触发文件上传,或者让用户选择保存后的PDF再上传)

在Handler中解析PDF并提取签名数据

接下来用PDF处理库(推荐iTextSharp或iText 7)在Handler中解析上传的PDF,提取数字签名信息。以下是具体的C#代码示例:

1. 获取上传的PDF文件流

在Handler的ProcessRequest方法中,先获取上传的PDF文件:

public void ProcessRequest(HttpContext context)
{
    // 假设表单中文件上传控件的name为"signaturePdf"
    HttpPostedFile pdfFile = context.Request.Files["signaturePdf"];
    if (pdfFile == null || pdfFile.ContentLength == 0)
    {
        context.Response.Write("未接收到带签名的PDF文件");
        return;
    }

    // 调用解析方法提取签名,替换成实际的用户ID
    ExtractAndSaveSignature(pdfFile.InputStream, userId);
}

2. 解析PDF并提取签名信息

用iTextSharp编写解析方法,提取签名的字节数据、签名者信息等:

private void ExtractAndSaveSignature(Stream pdfStream, int userId)
{
    using (PdfReader reader = new PdfReader(pdfStream))
    {
        AcroFields acroFields = reader.AcroFields;
        // 获取所有签名字段的名称
        List<string> signatureNames = acroFields.GetSignatureNames();
        
        foreach (string sigName in signatureNames)
        {
            // 获取签名对象
            PdfSignature signature = acroFields.GetSignature(sigName);
            
            // 获取签名的原始字节数据(可存储到数据库)
            byte[] signatureData = signature.GetContents();
            
            // 获取签名者的显示名称
            string signerName = signature.GetName();
            
            // 获取签名时间
            DateTime? signTime = signature.GetDate();
            
            // 验证签名有效性(可选,确保签名未被篡改)
            bool isSignatureValid = acroFields.VerifySignature(sigName);
            
            // 将签名数据、用户ID、签名信息存入数据库
            // 示例:使用ADO.NET或ORM执行插入操作
            // 数据库字段建议用VARBINARY(MAX)存储signatureData
            SaveToDatabase(userId, signatureData, signerName, signTime, isSignatureValid);
        }
    }
}

private void SaveToDatabase(int userId, byte[] signatureData, string signerName, DateTime? signTime, bool isValid)
{
    // 实现你的数据库存储逻辑,比如:
    // using (SqlConnection conn = new SqlConnection(你的连接字符串))
    // {
    //     string sql = "INSERT INTO DigitalSignatures (UserId, SignatureData, SignerName, SignTime, IsValid) VALUES (@UserId, @SignatureData, @SignerName, @SignTime, @IsValid)";
    //     SqlCommand cmd = new SqlCommand(sql, conn);
    //     cmd.Parameters.AddWithValue("@UserId", userId);
    //     cmd.Parameters.AddWithValue("@SignatureData", signatureData);
    //     // 其他参数...
    //     conn.Open();
    //     cmd.ExecuteNonQuery();
    // }
}

注意事项

  • PDF库选择:iTextSharp是.NET环境下处理PDF的常用库,若用.NET Core/.NET 5+,建议使用iText 7(注意许可证:iText 7采用AGPL协议,商业使用需购买许可)
  • 签名验证:如果需要确保签名的合法性,一定要调用VerifySignature方法验证,避免存储无效或被篡改的签名
  • 数据库字段类型:存储签名字节数据时,数据库字段要选择支持大二进制数据的类型(如SQL Server的VARBINARY(MAX)

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

火山引擎 最新活动