繁体   English   中英

如何查看pdf文件是否有密码保护?

[英]How to check pdf file is password protected?

如何在java中查看pdf文件是否有密码保护? 我知道有几个工具/库可以做到这一点,但我想知道仅使用 java 中的程序是否可行。

您可以使用 PDFBox:

http://pdfbox.apache.org/

代码示例:

try
{
    document = PDDocument.load( yourPDFfile );

    if( document.isEncrypted() )
    {
      //ITS ENCRYPTED!
    }
}

使用Maven?

<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0</version>
</dependency>

更新

根据 mkl 在此答案下方的评论,似乎规范允许两种类型的 PDF 结构:(1) 交叉引用表 (2) 交叉引用流。 以下解决方案仅针对第一种类型的结构。 需要更新此答案以解决第二种类型。

====

上面提供的所有答案都参考了一些第三方库,这是 OP 已经知道的。 OP 要求使用本机 Java 方法。 我的回答是肯定的,你可以做到,但需要做很多工作。

这将需要一个两步过程:

第 1 步确定 PDF 是否已加密

根据 Adob​​e 的 PDF 1.7 规范(第 97 和 115 页),如果预告片记录包含密钥“\\Encrypted”,则 pdf 将被加密(加密可以是简单的密码保护或 RC4 或 AES 或某些自定义加密)。 这是一个示例代码:

    Boolean isEncrypted = Boolean.FALSE;
    try {
        byte[] byteArray = Files.readAllBytes(Paths.get("Resources/1.pdf"));
        //Convert the binary bytes to String. Caution, it can result in loss of data. But for our purposes, we are simply interested in the String portion of the binary pdf data. So we should be fine.
        String pdfContent = new String(byteArray);
        int lastTrailerIndex = pdfContent.lastIndexOf("trailer");
        if(lastTrailerIndex >= 0 && lastTrailerIndex < pdfContent.length()) {
            String newString =  pdfContent.substring(lastTrailerIndex, pdfContent.length());
            int firstEOFIndex = newString.indexOf("%%EOF");
            String trailer = newString.substring(0, firstEOFIndex);
            if(trailer.contains("/Encrypt"))
                isEncrypted = Boolean.TRUE;
        }
    }
    catch(Exception e) {
        System.out.println(e);
        //Do nothing
    }

第 2 步找出加密类型

这一步比较复杂。 我还没有代码示例。 但这是算法:

  1. 从上面的步骤 1 中读取的预告片中读取密钥“/Encrypt”的值。 例如,值为 288 0 R。
  2. 查找字节“288 0 obj”。 这是文档中“加密字典”对象的位置。 该对象边界以字符串“endobj”结束。
  3. 在此对象中查找键“/Filter”。 “过滤器”是标识文档安全处理程序的过滤器。 如果“/Filter”的值为“/Standard”,则文档使用内置的基于密码的安全处理程序。

如果您只想知道 PDF 是否已加密,而不必担心加密是采用所有者/用户密码形式还是某些高级算法,则不需要上述步骤 2。

希望这可以帮助。

使用iText pdf API,我们可以识别受密码保护的 PDF。

例子 :

    try {
            new PdfReader("C:\\Password_protected.pdf");            
        } catch (BadPasswordException e) {
            System.out.println("PDF is password protected..");
        } catch (Exception e) {
            e.printStackTrace();
        }

您可以验证pdf,即它可以通过使用Itext 可读可写。

以下是代码片段,

boolean isValidPdf = false;
try {
    InputStream tempStream = new FileInputStream(new File("path/to/pdffile.pdf"));
    PdfReader reader = new PdfReader(tempStream);
    isValidPdf = reader.isOpenedWithFullPermissions();
    } catch (Exception e) {
        isValidPdf = false;
    }

java 答案中的正确操作方法是每个@vhs。

然而,在任何应用程序中,最简单的是使用非常轻量级的 pdfinfo 工具来过滤加密状态,在这里使用 windows cmd 我可以立即得到一份报告,同一文件的两个不同副本被加密

>forfiles /m *.pdf /C "cmd /c echo @file &pdfinfo @file|find /i \"Encrypted\""

"Certificate (9).pdf"
Encrypted:      no

"ds872 source form.pdf"
Encrypted:      AES 128-bit

"ds872 filled form.pdf"
Encrypted:      AES 128-bit

"How to extract data from a particular area in a PDF file - Stack Overflow.pdf"
Encrypted:      no

"Test.pdf"
Encrypted:      no

>

解决方案:

1) 安装 PDF 解析器http://www.pdfparser.org/

2) 在此部分编辑 Parser.php:

if (isset($xref['trailer']['encrypt'])) {
echo('Your Allert message');
exit();}

3)在你的 .php 表单帖子(例如upload.php)中插入:

for the first require  '...yourdir.../vendor/autoload.php';

然后写这个函数:

function pdftest_is_encrypted($form) {
$parser = new \Smalot\PdfParser\Parser();
$pdf    = $parser->parseFile($form);
}

然后调用函数

pdftest_is_encrypted($_FILES["upfile"]["tmp_name"]);

这就是全部,如果您尝试使用密码加载 PDF,系统将返回错误“您的警报消息”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM