HTML转PDF不支持原生加密,需在生成时由工具如wkhtmltopdf、pdfkit或weasyprint通过参数添加AES-128加密,或用qpdf事后处理;仅防直接打开,不防截图、OCR等。

HTML 转 PDF 本身不支持原生加密
HTML 是纯文本标记语言,浏览器渲染时没有加密能力;PDF 加密是生成 PDF 文件时由 PDF 写入器(如 pdfkit、weasyprint、wkhtmltopdf)在输出阶段添加的。所以“HTML 加密再转 PDF”这个思路行不通——你不能靠混淆 HTML 源码来保护最终 PDF 内容。
wkhtmltopdf 添加用户密码和所有者密码
wkhtmltopdf 是最常用的命令行 HTML→PDF 工具,它支持通过参数直接写入 PDF 标准加密(AES-128),但仅限于生成时设置,无法事后加密。
-
--user-password:设置打开密码(用户密码),输入错误则无法查看 -
--owner-password:设置权限密码(所有者密码),可绕过用户密码并修改权限 -
--no-print、--no-copy等限制打印/复制/编辑等操作(需配合 owner 密码生效)
wkhtmltopdf --user-password "123" --owner-password "admin" --no-copy --no-print input.html output.pdf
⚠️ 注意:--user-password 和 --owner-password 必须同时指定才启用加密;只设一个会静默忽略。生成后用 Adobe Acrobat 或 qpdf --show-encryption output.pdf 可验证是否生效。
Python 中用 pdfkit / weasyprint 实现加密
pdfkit(封装 wkhtmltopdf)和 weasyprint(纯 Python 渲染引擎)都支持传入加密参数,但行为不同:
立即学习“前端免费学习笔记(深入)”;
-
pdfkit:通过options字典透传命令行参数,例如{"user-password": "x", "owner-password": "y", "no-copy": ""} -
weasyprint:从 v54 开始支持encrypt参数,需显式调用write_pdf(..., encrypt=True, ...),且必须提供user_password和owner_password
from weasyprint import HTML
HTML("input.html").write_pdf("out.pdf",
encrypt=True,
user_password=b"read",
owner_password=b"edit",
allow_copy=False,
allow_print=False
)
⚠️ 注意:weasyprint 的密码必须是 bytes 类型;pdfkit 对密码类型无强制要求但建议用字符串。两者均不支持 AES-256,仅 AES-128(PDF 1.4+ 标准)。
生成后用 qpdf 补加密或改权限
如果已生成未加密 PDF,或想批量处理、替换密码、升级加密强度,可用 qpdf 命令行工具(比重新渲染更轻量):
- 添加密码并禁用复制:
qpdf --encrypt "u-pwd" "o-pwd" 256 --modify=none --extract=n input.pdf output.pdf - 仅升级加密(不改密码):
qpdf --encrypt "" "" 256 --use-aes=y input.pdf output.pdf - 移除密码(需知道 owner 密码):
qpdf --password="o-pwd" --decrypt input.pdf output.pdf
这是真正灵活的方案:无论你用什么工具生成 PDF,只要没被禁止解密(比如设置了 --force 或用了硬件 DRM),qpdf 都能接管加密逻辑。很多生产环境会把渲染和加密拆成两步,避免在 HTML 渲染服务中嵌入密码逻辑。
真正容易被忽略的是:PDF 加密只防“直接打开”,不防截图、OCR、内存抓取或调试器读取渲染后的 DOM。如果你要保护敏感内容,得考虑服务端动态水印、分片加载、或彻底放弃 PDF 下载,改用受控 Web 阅读器。











