Java 如何检查pdf文件是否受密码保护i

Java 如何检查pdf文件是否受密码保护i,java,pdf,Java,Pdf,如何在java中检查pdf文件是否受密码保护。。 我知道有几种工具/库可以做到这一点,但我想知道,仅使用java编程是否可以做到这一点。 提前感谢。您可以使用PDFBox: 代码示例: try { document = PDDocument.load( yourPDFfile ); if( document.isEncrypted() ) { //ITS ENCRYPTED! } } 使用maven <dependency>

如何在java中检查pdf文件是否受密码保护。。 我知道有几种工具/库可以做到这一点,但我想知道,仅使用java编程是否可以做到这一点。 提前感谢。

您可以使用PDFBox:

代码示例:

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>

org.apache.pdfbox
pdfbox
2
使用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();
        }
解决方案:

1) 安装PDF解析器

2) 在本节中编辑Parser.php:

if (isset($xref['trailer']['encrypt'])) {
echo('Your Allert message');
exit();}
3) 在.php表单post(例如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,系统将返回一个错误“Your Allert message”

您可以验证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;
    }

更新

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

====

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

这将需要两个步骤:

步骤1确定PDF是否加密

根据Adobe的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
    }
Boolean isEncrypted=Boolean.FALSE;
试一试{
byte[]byteArray=Files.readAllBytes(path.get(“Resources/1.pdf”);
//将二进制字节转换为字符串。注意,这可能会导致数据丢失。但出于我们的目的,我们只对二进制pdf数据的字符串部分感兴趣。因此,我们应该很好。
字符串pdfContent=新字符串(byteArray);
int lastTrailerIndex=pdfContent.lastIndexOf(“拖车”);
如果(lastTrailerIndex>=0&&lastTrailerIndex
步骤2找出加密类型

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

  • 按照上面步骤1中的读取,从尾部读取密钥“/加密”的值。例如,该值为288 0 R
  • 查找字节“288 0 obj”。这是文档中“加密字典”对象的位置。此对象边界在字符串“endobj”处结束
  • 在此对象中查找键“/过滤器”。“过滤器”是标识文档安全处理程序的过滤器。如果“/Filter”的值为“/Standard”,则文档使用内置的基于密码的安全处理程序 如果您只想知道PDF是否已加密,而不必担心加密是否以所有者/用户密码或某些高级算法的形式进行,则不需要执行上述步骤2


    希望这能有所帮助。

    您回答了自己的问题。使用像itext这样的开源库,编写一个java程序进行测试。我想其中一些工具/库是用纯java
    java
    编写的(而其他一些工具/库可以用其他语言编写,但这不是主题问题),不是吗?:)如果是这样,为什么不能编写自己的密码检查实现呢?正如@aga所指出的,显然可以在Java中实现。因此,您的问题很可能遗漏了一些您没有提到的附加要求。请解释您的要求。您的答案是关于PHP的,但这个问题需要一个Java解决方案。如果pdf使用交叉引用流而不是表,这是不起作用的。@mkl您能用一个例子详细说明一下吗?如果需要,我很乐意更新我的答案。我们的目标是帮助社区提供最有效的答案。使用交叉引用流的pdf没有代码所要求的预告片。相反,拖车条目被添加到交叉引用流字典中。@mkl,请附上一个使用外部参照流而不是外部参照表的PDF示例?说明书明确说明加密信息存储在拖车字典中。因为我目前只使用智能手机,所以我手头没有样本文件。但只需看看规范ISO 32000-1第7.5.8节“交叉引用流”:交叉引用流是流对象(见7.3.8“流对象”),包含字典和数据流。每个交叉参考流包含相当于一个交叉参考节的交叉参考表(见7.5.4,“交叉参考表”)和拖车(见7.5.5,“文件拖车”)的信息。iText受AGPL许可。因此,我建议使用PDFBox。由于pdf从未打开,阅读器不够。第二行应该是新的PdfDocument(新的PdfReader(filePath));使用
    getNumberOfPages()