zip文件加密、解密解压实操,附带文件上传安全检查

Zip4J 使用

今天接触到一个要解压上传的加密zip的需求,这里使用 zip4j 来实现加密解密。

依赖

<dependency>
    <groupId>net.lingala.zip4j</groupId>
    <artifactId>zip4j</artifactId>
    <version>2.9.0</version>
</dependency>

加密

/** * 添加普通文件为zip文件 * * @param srcPath 普通文件路径 E:\\test_zip_file\\image.png * @param destPath 要生成的zip文件路径 E:\\test_zip_file\\image.zip * @param password 加密密钥,为空时不加密 123456 * @throws ZipException zip异常 */
public static void zip(String srcPath, String destPath, String password) throws ZipException { 
    File srcFile = new File(srcPath);

    //创建目标文件
    ZipFile zipfile = new ZipFile(destPath);

    ZipParameters param = new ZipParameters();
    if (StringUtils.isNotBlank(password)) { 
        zipfile.setPassword(password.toCharArray());
        param.setEncryptFiles(true);
        param.setEncryptionMethod(EncryptionMethod.ZIP_STANDARD);
    }

    zipfile.addFile(srcFile, param);
}

zipfile.setPassword(char[]):设置压缩文件的密码;

param.setEncryptFiles(true);
param.setEncryptionMethod(EncryptionMethod.ZIP_STANDARD);

设置加密和加密的算法,还可以选择 EncryptionMethod 中的其他枚举

参考:https://github.com/srikanth-lingala/zip4j

解压(解密)

/** * 解压加密zip文件 * * @param files 客户端上送的加密zip文件 * @return 解压后的真实文件 */
public static File[] unzip(MultipartFile[] files) { 
    List<File> list = new ArrayList<>();
    Arrays.stream(files).forEach(file -> { 
        String filename = file.getOriginalFilename();
        if (Objects.isNull(filename)) { 
            LogUtils.error(log, "文件名为空:filename:{}", filename);
            CommonException.throwExp(ResultCode.INVALID_FILE_SUFFIX);
        }

        // 加密密钥 【这里以文件名作为密钥,实际可使用更安全的密钥】
        String key = FileNameUtil.mainName(filename);
        String tempPath = workDir + "temp" + File.separator + filename + "-" + UUID.fastUUID() + File.separator;
        LogUtils.info(log, "zip加密密钥:{},临时文件目录:{}", key, tempPath);

        ZipFile encryptFile = new ZipFile(AppFileUtils.multipartFileToFile(file));
        encryptFile.setPassword(key.toCharArray());

        try { 
            encryptFile.extractAll(tempPath);
        } catch (ZipException e) { 
            LogUtils.error(log, "解压加密zip文件到临时目录异常: {}", e);
            CommonException.throwExp(ResultCode.AUDIT_RESOURCE_READ_ERROR);
        }

        // 获取解压出来的文件【这里只是读取临时目录的单个文件】
        File tempDirFile = getTempDirFile(tempPath);

        // 存储解压出来的临时文件,然后删除
        list.add(tempDirFile);
        // 这里使用的 hutool 的 api FileUtil.del
        deleteTempFiles(tempPath);
    });
    return list.toArray(new MultipartFile[0]);
}

zipfile.setPassword(char[]):设置压缩文件的密码;

ZipFile.extract(); :解压文件到指定路径

zip 文件安全检查

/** * 上传文件安全检查 * 1. 路径中不可包含../ * 2. 文件名必须是.zip格式 * 3. zip 必须加密 * * @param files 要上传的文件 */
public static void checkSecurity(MultipartFile[] files) { 
    if (AppListUtils.isEmpty(Arrays.asList(files))) { 
        LogUtils.warn(log, "上传文件为空");
        return;
    }

    Arrays.stream(files).forEach(file -> { 
        String fileName = file.getOriginalFilename();

        // 路径中不可包含../
        if (Objects.isNull(fileName) || fileName.contains("../")) { 
            LogUtils.error(log, "文件名称不合法");
            CommonException.throwExp(ResultCode.INVALID_FILE_SUFFIX);
        }

        String fileType = "";
        try { 
            // hutool
            fileType = FileTypeUtil.getType(file.getInputStream());
        } catch (Exception e) { 
            LogUtils.error(log, "获取文件输入流异常:{}", e);
        }

        // 文件名必须是.zip格式, 文件必须以zip后缀
        if (!FileUtil.isExtendCompliance(fileName, "zip") || !"zip".equals(fileType)) { 
            LogUtils.error(log, "文件后缀不合法");
            CommonException.throwExp(ResultCode.INVALID_FILE_SUFFIX);
        }

        // 必须是加密文件
        ZipFile zipFile = new ZipFile(AppFileUtils.multipartFileToFile(file));
        try { 
            if (!zipFile.isEncrypted()) { 
                LogUtils.error(log, "上传文件非加密文件");
                CommonException.throwExp(ResultCode.INVALID_FILE_SUFFIX);
            }
        } catch (ZipException e) { 
            LogUtils.error(log, "上传文件判断加密异常: {}", e);
            CommonException.throwExp(ResultCode.AUDIT_RESOURCE_READ_ERROR);
        }
    });
}
    原文作者:一壶浊酒伴余生
    原文地址: https://blog.csdn.net/Ep_Little_prince/article/details/122331776
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞