使用iTextSharp打开受密码保护的pdf文件

时间:2021-12-17 00:36:43

I'm making an application that should display PDFs with password. This is my code:

我正在制作一个应该显示带密码的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 = "<script language='Javascript'>alert('File Not Found! Call Records Department for verification. ')</script>";
            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();
    }
}

My code has no problem opening pdf files without password but it can't open pdfs with password even though the password is supplied. The application executes the catch instead. What seems to be wrong with my code?

我的代码在没有密码的情况下打开pdf文件没有问题,但即使提供了密码也无法用密码打开pdf。应用程序执行catch。我的代码似乎有什么问题?

EDIT: I removed the Catch to see the exception thrown.

编辑:我删除了Catch以查看抛出的异常。

Exception Details: System.ArgumentException: PdfReader not opened with owner password

异常详细信息:System.ArgumentException:PdfReader未使用所有者密码打开

It says the source of the error is Line 51.

它说错误的来源是第51行。

Line 49:    while (i < pages)
Line 50:    {
Line 51:         pdfCopy.AddPage(pdfCopy.GetImportedPage(thepdfReader, i + 1));
Line 52:         i += 1;
Line 53:    }

2 个解决方案

#1


18  

For certain operations on encrypted documents iText(Sharp) requires that the document not merely is opened with the user password but instead with the owner password. This corresponds to the definition of these passwords in the PDF specification:

对于加密文档的某些操作,iText(夏普)要求不仅使用用户密码打开文档,而且使用所有者密码打开文档。这对应于PDF规范中这些密码的定义:

Whether additional operations shall be allowed on a decrypted document depends on which password (if any) was supplied when the document was opened and on any access restrictions that were specified when the document was created:

是否允许对解密文档执行其他操作取决于打开文档时提供的密码(如果有)以及创建文档时指定的任何访问限制:

  • Opening the document with the correct owner password should allow full (owner) access to the document. This unlimited access includes the ability to change the document’s passwords and access permissions.
  • 使用正确的所有者密码打开文档应该允许完全(所有者)访问文档。这种无限制访问包括更改文档密码和访问权限的功能。
  • Opening the document with the correct user password (or opening a document with the default password) should allow additional operations to be performed according to the user access permissions specified in the document’s encryption dictionary.
  • 使用正确的用户密码打开文档(或使用默认密码打开文档)应允许根据文档加密字典中指定的用户访问权限执行其他操作。

(section 7.6.3.1 in ISO 32000-1)

(ISO 32000-1中的第7.6.3.1节)

iText(Sharp) currently does not check in detail the user access permissions specified in the document’s encryption dictionary but instead always requires the owner password for operations requiring certain permissions, and copying whole pages from a document definitively is one of them.

iText(夏普)目前没有详细检查文档加密字典中指定的用户访问权限,而是始终要求所有者密码用于需要特定权限的操作,并且最终从文档复制整个页面就是其中之一。

This been said, the iText(Sharp) developers are very much aware (due to many such questions asked)

有人说,iText(夏普)开发人员非常清楚(由于提出了许多这样的问题)

  • that iText(Sharp) users may be entitled to execute such operations even without the owner password on account of the before mentioned user access permissions specified in the document’s encryption dictionary,
  • iText(夏普)用户可能有权在没有所有者密码的情况下执行此类操作,因为前面提到的文档加密字典中指定的用户访问权限,
  • that there are myriad PDFs to which their respective owners applied an owner password (to prevent misuse by others) and then forgot it (or by using a randomly generated one never knew it to start with), and
  • 有无数的PDF,他们各自的所有者应用了所有者密码(以防止被他人滥用),然后忘记它(或通过使用随机生成的一个从来不知道它开始),和
  • that iText(Sharp) (being open source) can easily be patched by anyone not to respect the differences between user and owner password.
  • iText(夏普)(开源)可以很容易地被任何人修补,不要尊重用户和所有者密码之间的差异。

To allow users to do what they are entitled to and to prevent the spreading of patched copies of the library, iText(Sharp) contains an override for this test in the PdfReader class:

为了允许用户执行他们有权使用的内容并防止扩展修补的库副本,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;

Thus, by setting

因此,通过设置

PdfReader.unethicalreading = true;

you globally override this permission checking mechanism.

全局覆盖此权限检查机制。

Please respect the rights of PDF authors and only use this override if you indeed are entitled to execute the operations in question.

请尊重PDF作者的权利,如果您确实有权执行相关操作,请仅使用此覆盖。

#2


0  

I applied this workaround and it works:

我应用此解决方法,它的工作原理:

private void fixIssue(PdfReader pdfReader) throws Exception {
        Field f = pdfReader.getClass().getDeclaredField("ownerPasswordUsed");
        f.setAccessible(true);
        f.setBoolean(pdfReader, true);

}

#1


18  

For certain operations on encrypted documents iText(Sharp) requires that the document not merely is opened with the user password but instead with the owner password. This corresponds to the definition of these passwords in the PDF specification:

对于加密文档的某些操作,iText(夏普)要求不仅使用用户密码打开文档,而且使用所有者密码打开文档。这对应于PDF规范中这些密码的定义:

Whether additional operations shall be allowed on a decrypted document depends on which password (if any) was supplied when the document was opened and on any access restrictions that were specified when the document was created:

是否允许对解密文档执行其他操作取决于打开文档时提供的密码(如果有)以及创建文档时指定的任何访问限制:

  • Opening the document with the correct owner password should allow full (owner) access to the document. This unlimited access includes the ability to change the document’s passwords and access permissions.
  • 使用正确的所有者密码打开文档应该允许完全(所有者)访问文档。这种无限制访问包括更改文档密码和访问权限的功能。
  • Opening the document with the correct user password (or opening a document with the default password) should allow additional operations to be performed according to the user access permissions specified in the document’s encryption dictionary.
  • 使用正确的用户密码打开文档(或使用默认密码打开文档)应允许根据文档加密字典中指定的用户访问权限执行其他操作。

(section 7.6.3.1 in ISO 32000-1)

(ISO 32000-1中的第7.6.3.1节)

iText(Sharp) currently does not check in detail the user access permissions specified in the document’s encryption dictionary but instead always requires the owner password for operations requiring certain permissions, and copying whole pages from a document definitively is one of them.

iText(夏普)目前没有详细检查文档加密字典中指定的用户访问权限,而是始终要求所有者密码用于需要特定权限的操作,并且最终从文档复制整个页面就是其中之一。

This been said, the iText(Sharp) developers are very much aware (due to many such questions asked)

有人说,iText(夏普)开发人员非常清楚(由于提出了许多这样的问题)

  • that iText(Sharp) users may be entitled to execute such operations even without the owner password on account of the before mentioned user access permissions specified in the document’s encryption dictionary,
  • iText(夏普)用户可能有权在没有所有者密码的情况下执行此类操作,因为前面提到的文档加密字典中指定的用户访问权限,
  • that there are myriad PDFs to which their respective owners applied an owner password (to prevent misuse by others) and then forgot it (or by using a randomly generated one never knew it to start with), and
  • 有无数的PDF,他们各自的所有者应用了所有者密码(以防止被他人滥用),然后忘记它(或通过使用随机生成的一个从来不知道它开始),和
  • that iText(Sharp) (being open source) can easily be patched by anyone not to respect the differences between user and owner password.
  • iText(夏普)(开源)可以很容易地被任何人修补,不要尊重用户和所有者密码之间的差异。

To allow users to do what they are entitled to and to prevent the spreading of patched copies of the library, iText(Sharp) contains an override for this test in the PdfReader class:

为了允许用户执行他们有权使用的内容并防止扩展修补的库副本,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;

Thus, by setting

因此,通过设置

PdfReader.unethicalreading = true;

you globally override this permission checking mechanism.

全局覆盖此权限检查机制。

Please respect the rights of PDF authors and only use this override if you indeed are entitled to execute the operations in question.

请尊重PDF作者的权利,如果您确实有权执行相关操作,请仅使用此覆盖。

#2


0  

I applied this workaround and it works:

我应用此解决方法,它的工作原理:

private void fixIssue(PdfReader pdfReader) throws Exception {
        Field f = pdfReader.getClass().getDeclaredField("ownerPasswordUsed");
        f.setAccessible(true);
        f.setBoolean(pdfReader, true);

}