Java 使用Apache POI创建受密码保护的Excel文件?

Java 使用Apache POI创建受密码保护的Excel文件?,java,excel,apache-poi,xls,Java,Excel,Apache Poi,Xls,我正在开发一个简单的Java程序,使用(ApachePOI)API创建Excel文件。 我使用Oracle10g作为数据库,并使用ojdbc14 JAR文件 我有一个名为USERINFO的表,有三列,即USERNAME,PASSWORD,和NAME. 现在使用ApachePOI,我已经能够将所有行放入Excel文件中 由于该文件包含用户名和密码等敏感数据,因此我希望对其进行密码保护。 在论坛上,我发现了如何读取受密码保护的文件,而不是如何创建它们。 那么我如何才能做到这一点呢?我经常发现,要做更

我正在开发一个简单的Java程序,使用(ApachePOI)API创建Excel文件。 我使用Oracle10g作为数据库,并使用ojdbc14 JAR文件

我有一个名为USERINFO的表,有三列,即
USERNAME
PASSWORD
,和
NAME.
现在使用ApachePOI,我已经能够将所有行放入Excel文件中

由于该文件包含用户名和密码等敏感数据,因此我希望对其进行密码保护。 在论坛上,我发现了如何读取受密码保护的文件,而不是如何创建它们。
那么我如何才能做到这一点呢?

我经常发现,要做更复杂的事情,一种有用的方法是在Excel中创建具有高级功能(例如宏)的电子表格,然后使用POI读取电子表格,填充并写出。POI通常会维护电子表格功能并添加数据

我还没有尝试过密码,但我怀疑这值得一试


有关更多信息,请参阅。

更新:自3.10版起,POI支持XLSX文件的加密和解密。看见以下内容仍然适用于XLS二进制工作簿

根据POI支持读取加密的XLS和XLSX文件。该页面未提及加密,这意味着不支持加密。它只返回少数几个结果,所有这些结果都与解密有关。我还查看了它们的加密实现的源代码,它似乎只处理解密。这并不奇怪;POI设计用于数据提取和搜索索引,而不是创建新的电子表格

正如其他人所建议的,通常可以通过在Excel中创建模板,然后使用POI填充数据来解决POI中缺少的功能。不幸的是,这对加密不起作用,因为加密电子表格的文件格式完全不同

如果您愿意购买商业软件,最新版本的具有对Excel支持的所有加密格式的完全读写支持。只需构造一个
EncryptedWorkBookHandle
,而不是普通的
WorkBookHandle
。这将使用未经修改的JRE支持的最强大的密码,RC4用于XLS,128位AES用于XLSX。如果您想在OOXML中使用256位AES,并且已经安装了,则可以使用
MSOfficeEncrypter

,一个流行的开源Java电子表格API,似乎根本不支持加密,商业发行。Actuate电子表格的文档似乎已经从网上消失了,所以我无法判断它是否支持加密

由于免费提供的Java电子表格API似乎都不支持编写加密的电子表格,因此,如果您不愿意使用商业软件,则需要找到一种解决方法。例如,您可以将电子表格写入加密的ZIP文件
java.util.zip
不支持加密,但它看起来支持加密


全面披露:我在Extentech工作,这是一家支持ExtenXLS的公司。

创建一个受密码保护的Excel文件,或使用现有模板并使其受密码保护。这将为用户提供“只读”访问权限。下面是一个示例,其中我有一个Excel文件,其中有一个密码“secret”:


与编写或修改现有模板的方式相同。完成后,覆盖模板。如果模板需要多次使用,您可能需要将模板复制到其他位置,然后使用代码对其进行修改。

以下程序将在给定的excel路径中生成受密码保护的excel文件

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.GeneralSecurityException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.poifs.crypt.EncryptionMode;
import org.apache.poi.poifs.crypt.Encryptor;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class MyTest1 {
    public static void main(String[] args) {
        File file = new File("C:\\Users\\Raju\\Desktop\\workbook1.xlsx");
        try {
            file.createNewFile();
            OutputStream fileOut = new FileOutputStream(file);
            XSSFWorkbook wb = new XSSFWorkbook();
            Sheet sheet = wb.createSheet();
            Row row = sheet.createRow(0);
            Cell cell = row.createCell(0);
            cell.setCellValue("Venu");
            wb.write(fileOut);
            wb.close();
            fileOut.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try (POIFSFileSystem fs = new POIFSFileSystem()) {
            EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
            // EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile,
            // CipherAlgorithm.aes192, HashAlgorithm.sha384, -1, -1, null);
            Encryptor enc = info.getEncryptor();
            enc.confirmPassword("hello");
            // Read in an existing OOXML file and write to encrypted output stream
            // don't forget to close the output stream otherwise the padding bytes aren't
            // added
            try (OPCPackage opc = OPCPackage.open(file, PackageAccess.READ_WRITE);
                    OutputStream os = enc.getDataStream(fs)) {
                opc.save(os);
            } catch (InvalidFormatException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (GeneralSecurityException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            // Write out the encrypted version
            try (FileOutputStream fos = new FileOutputStream(file)) {
                fs.writeFilesystem(fos);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (IOException e2) {
            // TODO Auto-generated catch block
            e2.printStackTrace();
        }
        System.out.println("Excel file exported");
    }
}
使用maven依赖项

<dependency>
 <groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.0.0</version>
</dependency>

org.apache.poi
poi ooxml
5.0.0

是的,我知道我们可以优化这么多代码。在高级阶段,程序正在运行

嗨,Brian,我不知道宏或高级功能。你能给我一些链接,在那里我可以得到一些帮助。我是POI的初学者。我的建议是在Excel中创建具有所需功能的spreasheet,然后使用POI读取并填充它。i、 e.这与您正在做的非常相似,但是使用现有的电子表格而不是新的电子表格,您告诉我一种可选的方法。我刚才所问的只是一个例子。事实上,在我的项目中有很多表,所以如果我为每个表手动创建excel文件会很困难。为什么?如果您知道上述方法不起作用,请告诉我,我将根据需要删除/修改。注意,虽然此代码确实创建了受Excel保护的工作簿,但生成的文件未加密。密码将散列并存储在未更改的文件中。由读取文件的软件来实施这种保护。如果加密正确,没有密码就无法读取文件。虽然我生成的excel文件受密码保护。它不是通过excel工具打开的。我可以用Plan Maker工具打开。有人遇到过这种情况吗?我最近在POI中添加了对基于xml的文件的加密支持,因此如果您更新您的答案,也就是说,第一段已经过时,那就太好了。关于提取设计:大多数POI API都是从读取功能支持开始的,但我不同意POI是专门为提取设计的(在我看来,这在2012年1月也是有效的),我同意kiwiwings。这个答案误导了我,检查最新的文档表明有加密支持。请更新答案。@kiwiwings我终于更新了。FWIW您不需要等待原始作者更新内容。StackOverflow是维基风格的,所以您可以随时使用它。
<dependency>
 <groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.0.0</version>
</dependency>