Java实现文件加密只读保护工具类
需求前景
项目中需要导出一份Excel
以及 Word
,并且需要用户自定义文件密码。于是便写了一个适用于Word
、Excel
的加密保护工具类
FileReadonlyProtectionUtil
/**
* @version 1.0.0
* @className: FileReadonlyProtectionUtil
* @description: 文件只读密码保护
* @author: LiJunYi
*/
@Slf4j
public class FileReadonlyProtectionUtil
{
/**
* word 执行只读保护
*
* @param filePath 文件路径
* @param password 文件解除保护密码,为 null则随机密码
* @throws IOException ioexception
*/
public static void enforceReadonlyProtectionWord(String filePath,String password) throws IOException
{
log.info("------ word执行只读保护开始 ------");
// try-with-resources 自动关闭文件流
Path path = Paths.get(filePath);
try(InputStream in = Files.newInputStream(path))
{
XWPFDocument document = new XWPFDocument(in);
if (StrUtil.isEmpty(password))
{
// 填写窗口模式,密码随机
document.enforceReadonlyProtection(RandomUtil.randomString(10), HashAlgorithm.sha512);
// 其他几种形式
// document.isEnforcedReadonlyProtection();不行
// document.enforceReadonlyProtection("123", HashAlgorithm.md5);wps无效
// document.enforceReadonlyProtection("123", HashAlgorithm.sha512);可以,但是依然可以复制
// document.enforceTrackedChangesProtection("123", HashAlgorithm.sha512);修订
// document.enforceCommentsProtection("123", HashAlgorithm.sha512);//批注
}else
{
// 填写窗口模式,指定密码
document.enforceReadonlyProtection(password, HashAlgorithm.sha512);
}
OutputStream oaf = Files.newOutputStream(path);
document.write(oaf);
oaf.flush();
oaf.close();
document.close();
log.info("------ word执行只读保护结束 ------");
}
}
/**
* excel 执行加密保护
*
* @param filePath 文件路径
* @param password 密码
* @throws Exception 异常
*/
public static void enforceEncryptProtectionExcel(String filePath,String password) throws Exception
{
File fileSource = new File(filePath);
// 文件加密
POIFSFileSystem fs = new POIFSFileSystem();
EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
Encryptor enc = info.getEncryptor();
enc.confirmPassword(password);
OPCPackage opc = OPCPackage.open(fileSource, PackageAccess.READ_WRITE);
OutputStream os = enc.getDataStream(fs);
opc.save(os);
opc.close();
// 导出之前一定要先关闭加密文件流,不然导出文件会损坏而无法打开
os.close();
// 导出
FileOutputStream fos = new FileOutputStream(fileSource);
fs.writeFilesystem(fos);
fos.close();
}
}
文件内容加密工具类
/**
* 文件内容加密工具类
* @author LiJunYi
*/
public class FileEncryptUtil {
private Key key;
private FileEncryptUtil(String str){
//生成秘钥
getKey(str);
}
/**
* 根据参数生成KEY
*/
private void getKey(String strKey){
try {
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(new SecureRandom(strKey.getBytes()));
this.key = generator.generateKey();
generator = null;
}catch (Exception e){
System.out.println(e.getMessage());
}
}
/**
* 对文件进行加密并保存目标文件destFile中
*
* @param file 要加密的文件
* @param destFile 加密后存放的文件名
*/
private void encrypt(String file,String destFile) throws Exception{
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE,this.key);
InputStream is = new FileInputStream(file);
OutputStream out = new FileOutputStream(destFile);
CipherInputStream cis = new CipherInputStream(is,cipher);
byte[] buffer = new byte[1024];
int r;
while ((r = cis.read(buffer)) > 0){
out.write(buffer,0,r);
}
cis.close();
is.close();
out.close();
}
/**
* 解密文件
* @param file 已加密的文件
* @param dest 解密后存放的文件名
*/
private void decrypt(String file, String dest) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE,this.key);
InputStream is = new FileInputStream(file);
OutputStream out = new FileOutputStream(dest);
CipherOutputStream cos = new CipherOutputStream(out,cipher);
byte[] buffer = new byte[1024];
int r;
while ((r = is.read(buffer)) >= 0){
System.out.println();
cos.write(buffer,0,r);
}
cos.close();
out.close();
is.close();
}
public static void main(String[] args) throws Exception {
FileEncryptUtil td = new FileEncryptUtil("aaa");
//加密
td.encrypt("G:/file.docx", "G:/file加密.docx");
//解密
td.decrypt("G:/file加密.docx", "G:/file.docx");
}
}