提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
1.首次登录
创建本地数据库->创建表->将数据存到表中->数据写入结束后将数据库写入加密文件->删除数据库文件。
2.需要使用数据时
将加密的数据库文件进行解密->创建数据库连接->进行数据获取操作->操作结束后将数据库文件加密后放入加密文件->删除数据库文件。
一、安装sqlite3
npm install sqlite3
二、对sqlites的数据库操作进行封装
const sqlite3 = require('sqlite3').verbose();
let sqlite = {};
sqlite.db = null;
sqlite.open = (filePath, key) => {
console.log('1 open', filePath);
return new Promise((resolve, reject) => {
sqlite.db = new sqlite3.Database(filePath, err => {
if (err) {
reject('Open error: ' + err.message)
} else {
resolve(filePath + ' opened');
}
})
})
}
// any query: insert/delete/update
sqlite.run = query => {
console.log('2 run', query);
return new Promise((resolve, reject) => {
sqlite.db.run(query, err => {
if (err) reject(err.message);
else resolve(true);
})
})
}
// first row read
sqlite.get = (query, params=[]) => {
console.log('2 get', query);
return new Promise((resolve, reject) => {
sqlite.db.get(query, params, (err, row) => {
if (err) reject('Read error: ' + err.message)
else resolve(row);
})
})
}
// set of rows read
sqlite.all = (query, params = []) => {
console.log('2 all',query);
return new Promise((resolve) => {
sqlite.db.all(query, params, (err, rows) => {
let res;
if (err) {
res = {
type: 'err',
data: err
};
} else {
res = {
type: 'rows',
data: rows
};
}
resolve(res);
})
})
}
// set of rows read
sqlite.exec = query => {
console.log('2 exec');
return new Promise((resolve, reject) => {
sqlite.db.exec(query, (err, rows) => {
if (err) reject('Read error: ' + err.message)
else resolve(rows);
})
})
}
// each row returned one by one
sqlite.each = (query, params, action) => {
console.log('2 each',query);
return new Promise((resolve, reject) => {
sqlite.db.serialize(() => {
sqlite.db.each(query, params, (err, row) => {
if (err) reject('Read error: ' + err.message)
else if (row) action(row);
})
sqlite.db.get('', (err, row) => {
resolve(true);
})
})
})
}
sqlite.close = (key) => {
return new Promise((resolve, reject) => {
sqlite.db.close();
resolve(true);
})
}
export default sqlite;
三、文件的加密、解密、读取、写入
const crypto = require('crypto');
const fs = require('fs');
/**
* 加密参数
* algorithm
* password 加密密钥
*/
const algorithm = 'aes-128-ctr';
const password = '123456789abcdefg';
const iv = 'abcdefg123456789'
/**
* 加密
* @param buffer 待加密文本
* @returns {Buffer} 加密之后文本
*/
export function Encrypt(buffer) {
let cipher = crypto.createCipheriv(algorithm, password, iv)
return Buffer.concat([cipher.update(buffer), cipher.final()]);
}
/**
* 解密
* @param buffer 待解密文本
* @returns {Buffer} 解密之后文本
*/
export function Decrypt(buffer){
let decipher = crypto.createDecipheriv(algorithm, password, iv)
return Buffer.concat([decipher.update(buffer), decipher.final()]);
}
/**
* 读取未加密文件
* @param filePath 文件路径
* @returns {Buffer} 数据流
*/
export function readPlaintextDatabaseFile(filePath) {
return fs.readFileSync(filePath);
}
/**
* 读取加密文件
* @param filePath 文件路径
* @returns {Buffer} 数据流
*/
export function readCiphertextDatabaseFile(filePath) {
let dataFlow = fs.readFileSync(filePath);
return Decrypt(dataFlow);
}
/**
* 明文写入数据
* @param filePath 路径
* @param data 待写入数据
*/
export function writePlaintextDatabaseFile(filePath, data) {
fs.writeFileSync(filePath, data);
}
/**
* 加密写入文件
* @param filePath 路径
* @param data 待写入数据
*/
export function writeCiphertextDatabaseFile(filePath, data) {
fs.writeFileSync(filePath, Encrypt(data));
}
/**
* 删除文件
* @param filePath 待删除文件路径
* @returns {Promise<Object>} 返回结果
*/
export function deleteFile(filePath) {
fs.unlinkSync(filePath);
}
四、数据库文件不存在时
a.判断数据库文件存在没
/**
* 判断 loginUsers 文件是否存在
* 否则创建 loginUsers 文件
* 返回参数 0:代表已经创建过数据表 1:代表没有创建过需要创建
* @return {Promise<unknown>}
*/
export function creatLoginUsersPort() {
return new Promise(resolve => {
try {
fs.readFileSync(loginUserFilePath);
resolve({code: 200, message: 'loginUsers读取成功',type:0});
} catch (e) {
fs.writeFileSync(loginUserFilePath, '');
resolve({code: 200, message: 'loginUsers创建成功',type:1});
}
})
}
b.不存在就创建本地数据库并创建表
/**
* 创建本地登录用户数据库
* @returns {Promise<unknown>}
*/
export async function creatLoginUserTablePort() {
// 打开数据库
await sqlite.open(loginUserDbPath, getKey());
// 执行SQL
await sqlite.run(createLoginUserColumnsTable());
await deleteDb();
}
/**
* 创建登录用户信息表
* @returns {string}
*/
export function createLoginUserColumnsTable() {
return `CREATE TABLE IF NOT EXISTS T_LOGIN_USER (
contact_id_ TEXT PRIMARY KEY,
ent_id_ TEXT,
ent_name_ TEXT,
username_ TEXT,
password_ TEXT,
ent_version_ TEXT,
update_time TEXT,
auto_login_ Long,
mindful_password_ Long
)`
}
c.当用户输入账号密码进行登录后将数据写入数据库
/**
* 登录
*/
function login(){
//判断用户是否存有过数据,存过就更新数据,没存就写入数据
this.selectUserInTable().then(async res => {
//更新数据
console.log('--------------更新数据');
this.userInfo.contactId = res.contactId;
await updateLoginUserData(this.userInfo);
}).catch(async() => {
//写入数据
console.log('--------------写入数据');
let contactId = this.uuid2();
this.userInfo.contactId = contactId;
await insertLoginUserDataPort(this.userInfo);
});
}
/**
* 读取加密文件并创建数据库文件
* 写入数据打开数据库连接
*/
async function creationDb(){
// 读取加密文件并解密数据
let dbData= await readCiphertextDatabaseFile(loginUserFilePath);
// 将解密数据写入数据库文件
await writePlaintextDatabaseFile(loginUserDbPath, dbData);
// 生成并打开数据库
await sqlite.open(loginUserDbPath, getKey());
}
/**
* 将数据库数据加密写入指定文件并删除数据库文件
*/
async function deleteDb(){
// 关闭连接
await sqlite.close(getKey());
//读取数据表数据
let data = readPlaintextDatabaseFile(loginUserDbPath);
//将数据表数据加密写入文件
await writeCiphertextDatabaseFile(loginUserFilePath,data);
// 删除数据库文件
await deleteFile(loginUserDbPath);
}
/**
* 写入登录用户数据
*/
export function insertLoginUserDataPort(userInfo) {
return new Promise(async (resolve, reject) => {
await creationDb();
const r = await sqlite.run(getLoginUserDataTable(userInfo));
await deleteDb();
if (r) {
resolve(r);
} else {
reject(0);
}
})
}
/**
* 登录用户更新/写入
* @param e
* @returns {string}
*/
export function getLoginUserDataTable(e) {
return `INSERT OR REPLACE INTO T_LOGIN_USER VALUES(
"${e.contactId}",
"${e.entId}",
"${e.entName}",
"${e.username}",
"${e.password}",
${e.entVersion},
"${e.updateTime}",
${e.autoLogin},
${e.mindfulPassword}
)`;
}
五、数据库文件存在时
/**
* 读取本地数据库文件,查看是否已有保存的账号密码
*/
readLocalFile() {
//获取用户信息
getLoginUserDataPort().then(data=>{
console.log(data,'-----------');
if (data && data.length !== 0) {
//判断是否自动登录
if(data[0].autoLogin === 1){
this.form.username = data[0].username;
this.form.password = data[0].password;
this.entId = data[0].entId;
this.userInfo = data[0];
const formData = {
username: this.form.username,
password: this.form.password,
loginType: "0",
};
getTokenApi(formData).then(res=>{
if (res.code == "200") {
this.token = res.data.token;
this.refreshToken = res.data.refreshToken;
this.chooseEnt();
}else{
this.$message.warning(res.msg);
}
})
}else if(data[0].mindfulPassword === 1){
this.form.password = data[0].password;
this.savePwd = true;
this.isPasswordEncrypt = false;
}
} else {
console.log("读取自动登录数据失败");
}
});
}
/**
* 查询本地已保存登录用户
* @returns {Promise<unknown>}
*/
export async function getLoginUserDataPort() {
await creationDb();
let dataInfo;
await sqlite.all(selectLoginUserData()).then((res)=>{
if(res.type === 'err'){
dataInfo = [];
}else{
dataInfo = res.data;
}
});
await sqlite.close(getKey());
// 删除数据库文件
await deleteFile(loginUserDbPath);
return new Promise((resolve, reject) => {
resolve(dataInfo);
})
}
/**
* 查询本地登录用户列表
* @returns {string}
*/
export function selectLoginUserData() {
return `select contact_id_ as contactId,
username_ as username,
password_ as password,
ent_id_ as entId,
ent_name_ as entName,
ent_version_ as entVersion,
update_time as updateTime,
auto_login_ as autoLogin,
mindful_password_ as mindfulPassword from T_LOGIN_USER order by update_time desc`;
}