原因:最近在用Sqlite存儲數據,因涉及數據安全,所以需要數據庫加密,Sqlite庫默認不帶加密功能 目前已知的對 SQLite 加密的工具主要有「[SQLite Encryption Extension (SEE)]、[SQLiteEncrypt]、[SQLiteCrypt]、[SQLCipher],但是這里面僅有 SQLCipher 有免費版本。 所以自己有個方案,針對Sqlite無法就是限制不能直接查看,那就對文件進行加密,需要連接的時候進行文件解密就可以了,如果大神有更好的解決方案,請告知,謝謝!
package com.ts.tools;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import JAVA.io.*;
/** 加密解密文件
* @author xhc
* @version 1.0.0
* @date 2022-10-31
*/
public class FileEnDe {
public static void main(String[] args) {
try {
//加密密碼
String key="abcdefghijklmnop";
//FileEnDe.encryptFile("D:/test.db",key,true);
//FileEnDe.decryptFile("D:/test.db",key);
System.out.println(FileEnDe.isLocked("D:/sysDb.db"));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 加密db文件(理論可以加密任何文件)
* @param filePath 文件路徑
* @param key16 加密密碼(必須16位)
* @return boolean
* @throws Exception
*/
public static boolean encryptFile(String filePath,String key16,boolean isReadOnly){
FileOutputStream fos =null;
boolean bFlag=false;
try {
if(FileUtil.exist(filePath)) {
byte[] key = key16.getBytes();
//取文件名稱含后綴
String fileName=FileUtil.getName(filePath);
//加密文件
SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key);
FileInputStream fis = new FileInputStream(filePath);
String newFilePath=filePath+"_e";
fos=new FileOutputStream(newFilePath);
aes.encrypt(fis, fos, true);
fos.close();
//刪除源文件,注意如果文件被使用會報:另一個程序正在使用此文件,進程無法訪問
boolean isDel=FileUtil.del(filePath);
if(isDel){
//重命名加密文件為源文件
FileUtil.rename(new File(newFilePath),fileName,true);
//設置只讀文件
if(isReadOnly) {
File f=new File(filePath);
f.setReadOnly();
}
}
bFlag=true;
}else{
throw new RuntimeException(filePath+" 文件不存在!");
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
IoUtil.close(fos);
}
return bFlag;
}
/**
* 解密Db庫
* @param filePath 文件路徑
* @param key16 加密密碼(必須16位)
* @return boolean
* @throws Exception
*/
public static boolean decryptFile(String filePath,String key16){
boolean bFlag=false;
FileOutputStream fos =null;
try {
if(FileUtil.exist(filePath)) {
byte[] key = key16.getBytes();
//取文件名稱含后綴
String fileName=FileUtil.getName(filePath);
//解密文件
SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key);
FileInputStream fis = new FileInputStream(filePath);
String newFilePath=filePath+"_d";
fos = new FileOutputStream(newFilePath);
aes.decrypt(fis, fos, true);
//注意,解密之后 fos 并未關閉,請先關閉
fos.close();
//刪除源文件,注意如果文件被使用會報:另一個程序正在使用此文件,進程無法訪問
boolean isDel=FileUtil.del(filePath);
if(isDel){
//重命名加密文件為源文件
FileUtil.rename(new File(newFilePath),fileName,true);
}
bFlag=true;
}else{
throw new RuntimeException(filePath+" 文件不存在!");
}
} catch (FileNotFoundException e) {
throw new RuntimeException(filePath+" 文件不存在!");
}catch (Exception e){
throw new RuntimeException(e);
}finally {
IoUtil.close(fos);
}
return bFlag;
}
/**
* 文件是否占用(采用重命名的方式)
* @param filePath 文件路徑
* @return boolean
*/
public static boolean isLocked(String filePath){
boolean bFlag=false;
String newFileName="";
String fileName="";
try {
if(FileUtil.exist(filePath)) {
// 采用重命名的方式,如果占用無法修改文件名稱,如果未占用修改新的文件名稱后再修改回來
fileName = FileUtil.getName(filePath);
newFileName = fileName + "_n";
FileUtil.rename(new File(filePath), newFileName, true);
}
} catch (Exception e) {
bFlag=true;
}finally {
//如果未占用修改新的文件名稱后再修改回來
if(!bFlag) {
FileUtil.rename(new File(filePath+"_n"), fileName, true);
}
}
return bFlag;
}
}