数据库密码明文加密在Node全栈项目中的尝试

之前参与的一个项目采用的是NodeJs+MongoDB数据库全栈开发,连接MongoDB数据库地址是写在nodejs的配置文件中实现调用,此前配置的数据库地址url的账号密码和IP地址是文明显示的,从安全性角度来看,如同在“裸奔”般危险。

为解决安全通报 〔2019〕05号工作要求AQ011项【严禁密钥/密码/口令等以明文形式存储在数据库、代码或配置文件中】,我们使用node-rsa对nodejs配置文件中存在的明文进行加密,下面来总结一下简单的rsa加密解密用法。

初始化环境

新建一个文件夹 node-rsa-demo , 终端进入,运行下面命令初始化

cd node-rsa-demo
npm init # 一路回车即可
npm install --save node-rsa

生成公钥私钥

先在 node-rsa-demo 文件夹下新建一个文件夹 pem 用来存放密钥的

然后再新建一个文件 index.js 写上如下代码

var NodeRSA = require('node-rsa')
var fs = require('fs')
function generator() {
 var key = new NodeRSA({ b: 512 })
 key.setOptions({ encryptionScheme: 'pkcs1' })
 var privatePem = key.exportKey('pkcs1-private-pem')
 var publicPem = key.exportKey('pkcs1-public-pem')
 fs.writeFile('./pem/public.pem', publicPem, (err) => {
 if (err) throw err
 console.log('公钥已保存!')
 })
 fs.writeFile('./pem/private.pem', privatePem, (err) => {
 if (err) throw err
 console.log('私钥已保存!')
 })
}
generator();

接着执行 node index.js ,结果如图:

然后你会发现在 pem 文件夹下生成了两个文件,即公钥和私钥

  • private.pem
  • public.pem

加密

加密配置文件config.db.url这个字符串

function encrypt() {
 fs.readFile('./pem/private.pem', function (err, data) {
 var key = new NodeRSA(data);
 let cipherText = key.encryptPrivate('mongodb://limoumou:[email protected]:8080/web', 'base64');
 console.log(cipherText);
 });
}
encrypt();

然后执行 node index.js 终端里会输出一串字符,结果如图:

jKonGONf+RDzcrMj7kPjyV68CuR7ipY7nBII9D2jO2+qZPY5oNxUlX57cVObYAhjTxowdbu3yb81XgGTNV94npPKtti78q68GVR3z46VuFAvYuS/it2JaeYB13OvEng9EchBa.........cwlGX+ATwhtDeZirf0S6rwdBg+y4RIvgkaM 的base64字符串,这就是用私钥加密后的密文了

解密

把上一步加密获得的密文复制粘贴到下面要解密的方法内

function decrypt() {
 fs.readFile('./pem/public.pem', function (err, data) {
 var key = new NodeRSA(data);
 let rawText = key.decryptPublic('jKonGONf+RDzcrMj7kPjyV68CuR7ipY7nBII9D2jO2+qZPY5oNxUlX57cVObYAhjTxowdbu3yb81XgGTNV94npPKtti78q68GVR3z46VuFAvYuS/it2JaeYB13O......cwlGX+ATwhtDeZirf0S6rwdBg+y4RIvgkaM', 'utf8');
 console.log(rawText);
 });
}
decrypt();

执行 node index.js 会发现又拿到 mongodb://limoumou:[email protected]:8080/web 这个数据库地址了

但是

fs.readFile()为异步加载方式,运行后rawText参数始终为空

try {    
	mongoose.connect( rawText, {useMongoClient: true}, function(err) {
        if (err) {
            console.log('数据库连接失败!');
        } else {
            console.log('数据库连接成功!');
        }
    });
} catch (error) {
    console.log(error);
}

报错提示为:Error: Invalid mongodb uri "". Must begin with "mongodb://",即先执行了数据库链接命令后执行解密操作

优化

采用fs.readFileSync()同步来读取公钥文件,优化如下:

var NodeRSA = require('node-rsa');
var key = new NodeRSA();
let rawText = '';
var publicData = fs.readFileSync('./pem/public.pem');
key = new NodeRSA(publicData);
var longString = config.db.url;
rawText = key.decryptPublic(longString, 'utf8');

这样即可正确执行连接数据库命令,到这里就算是完成了NodeJs加密解密配置文件数据库明文地址的问题,Over

改进

当目标任务完成,我们更多的,还要考虑程序的性能,运行效率,组织结构,和重用性等等。

以上到优化步骤的解决方案存在一个问题,网站在运行过程中会不断的请求数据库,那么就会不断的进行解密的操作,改进方案即是把加密解密的操作单独写在一个rsa.js放置在中间件中,解密后的值以参数的形式传送过来。

猜你喜欢

转载自blog.csdn.net/qq_33298964/article/details/129142030
今日推荐