在XSSF工作簿上设置密码保护

3
我希望为使用poi 3.14创建的xlsx文件添加密码保护。 文档声称这是可能的:http://poi.apache.org/encryption.html 我尝试使用示例,像这样:
    public static void main(String[] args)
{
    try(Workbook wb = new XSSFWorkbook())
    {

        //<...>
        try(ByteArrayOutputStream baos = new ByteArrayOutputStream())
        {
            wb.write(baos);
            byte[] res = baos.toByteArray();
            try(ByteArrayInputStream bais = new ByteArrayInputStream(res))
            {
                try(POIFSFileSystem fileSystem = new POIFSFileSystem(bais);) // Exception happens here
                {
                    EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
                    Encryptor enc = info.getEncryptor();
                    enc.confirmPassword("pass");
                    OutputStream encryptedDS = enc.getDataStream(fileSystem);
                    OPCPackage opc = OPCPackage.open(new File("example.xlsx"), PackageAccess.READ_WRITE);
                    opc.save(encryptedDS);
                    opc.close();
                }
            }
        }
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
}

很遗憾,示例中的代码不兼容XLSX文件,因此我收到以下异常:

The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)

可以有人帮忙吗?我找不到XLSX的正确替代品...

非常感谢大家的帮助。这是我的工作结果:

    public static void main(String[] args)
{
    try(Workbook wb = new XSSFWorkbook())
    {
        Sheet sheet = wb.createSheet();
        Row r = sheet.createRow(0);
        Cell cell = r.createCell(0);
        cell.setCellType(Cell.CELL_TYPE_STRING);
        cell.setCellValue("Test");
        try(POIFSFileSystem fileSystem = new POIFSFileSystem();)
        {
            EncryptionInfo info = new EncryptionInfo(EncryptionMode.standard);
            Encryptor enc = info.getEncryptor();
            enc.confirmPassword("pass");
            OutputStream encryptedDS = enc.getDataStream(fileSystem);
            wb.write(encryptedDS);
            FileOutputStream fos = new FileOutputStream("C:/example.xlsx");
            fileSystem.writeFilesystem(fos);
            fos.close(); 
        }
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
}

1
哪一行代码导致了这个异常? - Gagravarr
2
example.xslx(应为.xlsx)是否真的是Office 2007+ XML文件?您不需要使用OPCPackage,而可以直接将该文件按字节复制到encryptedDS中。但是,如果example.xslx是Excel 2003 XML计算表,那么打开加密文件也无法工作... - kiwiwings
感谢您的评论。我标记了出现异常的行(新的POIFSFileSystem)。"xslx"是一个打字错误.. - Mathis
1
打开一个错误条目,并附上您的 example.xlsx 文件 - 我需要查看该文件。 - kiwiwings
嗨,我提交了 https://bz.apache.org/bugzilla/show_bug.cgi?id=60363 。example.xlsx 文件不存在,但这并不重要,因为该行代码从未执行... - Mathis
1个回答

4
你误读了 OOXML 文件加密文档。因此,您错误地尝试使用错误的代码加载文件,而实际上您只需要保存它即可。

没有任何错误处理,你的代码基本上应该是

// Prepare
POIFSFileSystem fs = new POIFSFileSystem();
EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile, CipherAlgorithm.aes192, HashAlgorithm.sha384, -1, -1, null);

Encryptor enc = info.getEncryptor();
enc.confirmPassword("foobaa");

// Create the normal workbook
Workbook wb = new XSSFWorkbook();
Sheet s = wb.createSheet();
// TODO Populate

// Encrypt
OutputStream os = enc.getDataStream(fs);
wb.save(os);
opc.close();

// Save
FileOutputStream fos = new FileOutputStream("protected.xlsx");
fs.writeFilesystem(fos);
fos.close();  

你的代码在使用NPOI包的.NET上无法运行。请问你能告诉我如何让它正常工作吗?我不想安装Java。`POIFSFileSystem fs = new POIFSFileSystem();EncryptionInfo info = new EncryptionInfo(EncryptionMode.Agile, CipherAlgorithm.aes192, HashAlgorithm.sha384, -1, -1, null);Encryptor enc = info.Encryptor;enc.ConfirmPassword("foobaa");/* <== 异常在此处产生:EncryptedDocumentException。出现了出口限制,请安装JCE无限制权限策略文件。 */ - Pavel Hodek
尝试使用不同的构造函数参数,例如:var info = new EncryptionInfo(EncryptionMode.Agile) 并非所有软件环境都知道或允许使用所有密码/哈希算法。 - cly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接