js实现pdf签名
实现PDF签名的基本方法
使用JavaScript实现PDF签名通常涉及前端库或后端服务处理。以下是几种常见方法:
前端实现(浏览器环境)
使用PDF库如pdf-lib或pdf.js添加签名:
import { PDFDocument, rgb } from 'pdf-lib';
async function addSignatureToPDF(pdfBytes, signatureImage) {
const pdfDoc = await PDFDocument.load(pdfBytes);
const page = pdfDoc.getPages()[0];
// 添加签名图像
const signature = await pdfDoc.embedPng(signatureImage);
page.drawImage(signature, {
x: 50,
y: 50,
width: 100,
height: 50,
});
return await pdfDoc.save();
}
数字签名(加密验证)
使用node-forge或pkijs进行数字签名:
const forge = require('node-forge');
function signPDF(pdfBuffer, privateKeyPem) {
const privateKey = forge.pki.privateKeyFromPem(privateKeyPem);
const md = forge.md.sha256.create();
md.update(pdfBuffer.toString('binary'));
return privateKey.sign(md);
}
完整解决方案示例
依赖库选择
- 纯前端:
pdf-lib+ 画布签名(如signature_pad) - 后端处理:
pdfkit(Node.js)或iText(Java/Python桥接) - 全栈方案:前端收集签名图像,后端通过
PDFtk或Ghostscript合并
实现步骤
创建画布签名板(前端):
const canvas = document.getElementById('signature-pad');
const ctx = canvas.getContext('2d');
let drawing = false;
canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', stopDrawing);
function startDrawing(e) {
drawing = true;
draw(e);
}
function draw(e) {
if (!drawing) return;
ctx.lineWidth = 2;
ctx.lineCap = 'round';
ctx.strokeStyle = '#000';
ctx.lineTo(e.clientX, e.clientY);
ctx.stroke();
}
function stopDrawing() {
drawing = false;
ctx.beginPath();
}
将签名嵌入PDF(Node.js后端示例):
const { PDFDocument } = require('pdf-lib');
const fs = require('fs');
async function embedSignature(inputPath, outputPath, signatureImage) {
const pdfBytes = fs.readFileSync(inputPath);
const pdfDoc = await PDFDocument.load(pdfBytes);
const pngImage = await pdfDoc.embedPng(fs.readFileSync(signatureImage));
const pages = pdfDoc.getPages();
pages[0].drawImage(pngImage, {
x: 100,
y: 100,
width: 150,
height: 50,
});
fs.writeFileSync(outputPath, await pdfDoc.save());
}
安全注意事项
- 数字签名应使用证书颁发机构(CA)签发的密钥对
- 前端实现的图形签名需通过HTTPS传输防止篡改
- 考虑使用WebAssembly加速加密运算(如
libsodium.js) - 敏感操作建议在后端完成,避免暴露私钥
云服务方案
对于企业级需求,可集成第三方API:
- Adobe Sign API
- Docusign REST API
- PandaDoc电子签名服务
调用示例(以Docusign为例):
const axios = require('axios');
async function createEnvelopeWithSignature(docBase64, signerEmail) {
const response = await axios.post('https://demo.docusign.net/restapi/v2.1/envelopes', {
documents: [{
documentBase64: docBase64,
fileExtension: 'pdf'
}],
recipients: {
signers: [{
email: signerEmail,
tabs: {
signHereTabs: [{
xPosition: '100',
yPosition: '100'
}]
}
}]
}
}, {
headers: { Authorization: `Bearer ${accessToken}` }
});
return response.data;
}






