使用iTextSharp打开受密码保护的pdf文件
我正在制作一个应该显示带密码的PDF的应用程序。 这是我的代码:
protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { try { string filePath = Request.QueryString["filePath"]; if (filePath.ToUpper().EndsWith("PDF")) { copyPDF(filePath); } } catch { string message = "alert('File Not Found! Call Records Department for verification. ')"; ScriptManager.RegisterStartupScript(Page, this.GetType(), message, message, false); } } } public void copyPDF(string filePath) { iTextSharp.text.pdf.RandomAccessFileOrArray ra = new iTextSharp.text.pdf.RandomAccessFileOrArray(Server.MapPath(ResolveUrl(filePath))); if (ra != null) { System.IO.MemoryStream ms = new System.IO.MemoryStream(); byte[] password = System.Text.ASCIIEncoding.ASCII.GetBytes("Secretinfo"); iTextSharp.text.pdf.PdfReader thepdfReader = new iTextSharp.text.pdf.PdfReader(ra, password); int pages = thepdfReader.NumberOfPages; iTextSharp.text.Document pdfDoc = new iTextSharp.text.Document(); iTextSharp.text.pdf.PdfCopy pdfCopy = new iTextSharp.text.pdf.PdfCopy(pdfDoc, ms); pdfDoc.Open(); int i = 0; while (i < pages) { pdfCopy.AddPage(pdfCopy.GetImportedPage(thepdfReader, i + 1)); i += 1; } pdfDoc.Close(); Byte[] byteInfo = ms.ToArray(); Response.Clear(); Response.ContentType = "application/pdf"; Response.AddHeader("content-length", byteInfo.Length.ToString()); Response.BinaryWrite(byteInfo); Response.Flush(); Response.End(); } }
我的代码在没有密码的情况下打开pdf文件没有问题,但即使提供了密码也无法用密码打开pdf。 应用程序执行catch。 我的代码似乎有什么问题?
编辑 :我删除了Catch以查看抛出的exception。
exception详细信息 :System.ArgumentException:PdfReader未使用所有者密码打开
它说错误的来源是第51行。
Line 49: while (i < pages) Line 50: { Line 51: pdfCopy.AddPage(pdfCopy.GetImportedPage(thepdfReader, i + 1)); Line 52: i += 1; Line 53: }
对于加密文档的某些操作,iText(夏普)要求不仅使用用户密码打开文档,而且使用所有者密码打开文档。 这对应于PDF规范中这些密码的定义:
是否允许对解密文档执行其他操作取决于打开文档时提供的密码(如果有)以及创建文档时指定的任何访问限制:
- 使用正确的所有者密码打开文档应该允许完全(所有者)访问文档。 这种无限制访问包括更改文档密码和访问权限的function。
- 使用正确的用户密码打开文档(或使用默认密码打开文档)应允许根据文档加密字典中指定的用户访问权限执行其他操作。
( ISO 32000-1中的第7.6.3.1节)
iText(夏普)目前没有详细检查文档加密字典中指定的用户访问权限,而是始终要求所有者密码用于需要特定权限的操作,并且最终从文档复制整个页面就是其中之一。
有人说,iText(夏普)开发人员非常清楚(由于提出了许多这样的问题)
- iText(夏普)用户可能有权在没有所有者密码的情况下执行此类操作,因为前面提到的文档加密字典中指定的用户访问权限,
- 有无数的PDF,他们各自的所有者应用了所有者密码(以防止被他人滥用),然后忘记它(或通过使用随机生成的一个从来不知道它开始),和
- iText(夏普)(开源)可以很容易地被任何人修补,不要尊重用户和所有者密码之间的差异。
为了允许用户执行他们有权使用的内容并防止扩展修补的库副本,iText(Sharp)在PdfReader
类中包含对此测试的覆盖:
/** * The iText developers are not responsible if you decide to change the * value of this static parameter. * @since 5.0.2 */ public static bool unethicalreading = false;
因此,通过设置
PdfReader.unethicalreading = true;
全局覆盖此权限检查机制。
请尊重PDF作者的权利,如果您确实有权执行相关操作,请仅使用此覆盖。
我应用此解决方法,它的工作原理:
private void fixIssue(PdfReader pdfReader) throws Exception { Field f = pdfReader.getClass().getDeclaredField("ownerPasswordUsed"); f.setAccessible(true); f.setBoolean(pdfReader, true); }