针对“Nodejs环境Eggjs加签验签示例代码”的完整攻略,我将采用以下目录结构:
目录
背景
我们在进行接口对接的时候,通常都需要进行数据传输。然而,由于网络的不安全性,很多人都会考虑使用加密传输进行保护。但是,单纯的加密不足以满足安全需求。因此,我们引入了加签验策略。
加签验可以有效的保护数据的完整性,确保数据在传输的过程中没有被篡改。同时也可以确保数据的来源可信。虽然数据在传输过程中可能会被拦截和解密,但是由于加签的存在,攻击者无法篡改数据。
技术方案
我们采用Node.js下的Egg.js框架作为接口开发的工具,既可以快速的构建一个HTTP Server,同时也支持加签验的操作。
加签验策略
加签验策略的核心是通过两种不同的密钥进行加密和解密,分别为公钥和私钥。在一个系统中,由于公钥是公开的,因此,任何人都可以拿到公钥进行加密,而只有拥有私钥的人才能够进行解密。利用这种方式,我们可以在传输数据的过程中,利用私钥对数据进行签名,将签名和数据一起传输到接收方。接受方可以通过公钥进行解密签名,验证数据的完整性和来源可信。
示例代码(1):接收方验证
我们进行一个示例,假设现在我们有一个发送方A和接收方B的场景。A需要给B传输数据,并使用私钥签名。B需要使用公钥验证签名。
// 加载Egg.js的框架
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const egg = require('egg');
const root = path.resolve(__dirname, '..');
class AppBootHook {
constructor(app) {
this.app = app;
}
async didReady() {
// 加载私钥文件
const privatePem = fs.readFileSync(path.join(root, 'rsa', 'private.pem'));
const privateKey = privatePem.toString('ascii');
// 获取请求参数
const params = this.ctx.params;
// 获取签名和数据
const data = params.data;
const sign = params.sign;
// 删除签名参数
delete params.sign;
// 将参数编码并排序
const query = Object.keys(params).sort().map(key => {
const value = params[key];
return key + '=' + encodeURIComponent(value);
}).join('&');
// 验证签名
const verify = crypto.createVerify('RSA-SHA256');
verify.update(query);
verify.end();
if (!verify.verify(privateKey, sign, 'base64')) {
this.ctx.throw(400, 'invalid signature');
}
// 处理业务逻辑
// ...
// 返回响应
this.ctx.body = 'OK';
}
}
egg.startCluster({
baseDir: __dirname,
port: 7001,
workers: 1,
plugins: {
oauth: {
enable: true,
path: path.join(root, 'node_modules', 'egg-oauth2-server')
}
}
}, () => {});
上述代码,我们定义了一个Egg.js的middleware,需要在B端接收数据的时候使用该middleware进行校验。首先,我们加载私钥,然后我们获取request中的参数。我们获取到数据和签名后,需要将签名参数进行删除。接下来,我们将参数编码并排序。最后,我们生成一个Verify对象,并使用私钥进行签名校验。如果校验失败,我们将直接返回错误信息。如果校验成功,则可以处理业务逻辑。
示例代码(2):发送方加签
接下来,我们考虑A端如何进行签名的操作。我们先编写一个工具类:
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const root = path.resolve(__dirname, '..');
class SignUtil {
constructor(privateKeyPath) {
const privatePem = fs.readFileSync(path.join(root, privateKeyPath));
this.privateKey = privatePem.toString('ascii');
}
sign(data) {
const query = Object.keys(data).sort().map(key => {
const value = data[key];
return key + '=' + encodeURIComponent(value);
}).join('&');
const signer = crypto.createSign('RSA-SHA256');
signer.update(query);
signer.end();
return signer.sign(this.privateKey, 'base64');
}
}
module.exports = SignUtil;
上述代码,我们定义了一个工具类,用于生成签名。我们需要传入私钥文件的路径,然后我们定义了一个sign方法,其中我们首先获取到参数,并进行编码和排序。接下来,我们生成一个Sign对象,并使用私钥进行签名。最后,我们将签名进行Base64编码并返回。
然后,我们考虑如何在A端进行签名,可以在controller中进行调用:
const egg = require('egg');
const LoginController = egg.Controller;
const SignUtil = require('../utils/SignUtil');
class TestController extends LoginController {
async index() {
const query = this.ctx.query;
const signUtil = new SignUtil('../rsa/private.pem');
const sign = signUtil.sign(query);
this.ctx.body = {
...query,
sign
};
}
}
module.exports = TestController;
上述代码,我们首先引入了SignUtil工具类,并定义了一个index方法。我们首先获取到请求参数,并将请求参数和签名组合成一个对象进行返回。至此,我们完成了签名的操作。
总结
通过上述示例,我们可以看到,使用加签验策略可以有效保护数据的完整性和来源可信。通过公钥和私钥的组合,我们可以进行签名和验签的操作,确保数据的安全。同时,Egg.js框架也提供了非常方便的middleware和hooks操作,可以帮我们更加快速的完成开发任务。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Nodejs环境Eggjs加签验签示例代码 - Python技术站