Prevent copying pdf contents generated using iText

2019-08-09 08:50发布

问题:

We have a web application which generates a report and saves it in pdf using iText. We want to prevent user from copying the contents from this file. I thought this can be achieved by converting pdf contents to image and then add that image to pdf but it seems iText cannot convert pdf to an image.

Is there a way I can do this using iText?

回答1:

As @YuriyGalanter indicated, restrictive permissions in PDFs are primarily defined in the context of encryption in PDFs, cf. section 7.6.3.1 of the PDF specification ISO 32000-1:2008:

If passwords or access restrictions are specified, the document shall be encrypted, and the permissions and information required to validate the passwords shall be stored in the encryption dictionary. Documents in which only file attachments are encrypted shall use the same password as the user and owner password.

  • 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.

Thus, if a PDF is encrypted using an owner password but no user password, anyone can open the PDF and is restricted by the permissions selected during encryption. Only someone opening that PDF with its owner password is permitted has unlimited access to the PDF.

Obviously such a scheme can easily be broken and ´the protection removed. It depends on the ethical behaviour of PDF processing software.

The example EncryptionPdf.java from chapter 12 of iText in Action — 2nd Edition demonstrates how to apply encryption using iText.

The method createPdf illustrates how to apply encryption when creating a new PDF:

public void createPdf(String filename) throws IOException, DocumentException {
    // step 1
    Document document = new Document();
    // step 2
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
    writer.setEncryption(USER, OWNER, PdfWriter.ALLOW_PRINTING, PdfWriter.STANDARD_ENCRYPTION_128);
    writer.createXmpMetadata();
    // step 3
    document.open();
    // step 4
    document.add(new Paragraph("Hello World"));
    // step 5
    document.close();
}

The method encryptPdf illustrates how to encrypt an existing PDF:

public void encryptPdf(String src, String dest) throws IOException, DocumentException {
    PdfReader reader = new PdfReader(src);
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    stamper.setEncryption(USER, OWNER,
        PdfWriter.ALLOW_PRINTING, PdfWriter.ENCRYPTION_AES_128 | PdfWriter.DO_NOT_ENCRYPT_METADATA);
    stamper.close();
    reader.close();
}

Here USER and OWNER are the user and owner passwords mentioned above.

The sample only sets one permission, PdfWriter.ALLOW_PRINTING; there are multiple other ones, simply inspect all the ALLOW_* constants of PdfWriter.