微信小程序解密敏感数据,前后端实操流程
本文以前后端代码实例,描述解密流程,阅读大约10分钟
01 序言:
微信小程序对用户敏感数据获取越来越严格,很多API只能拿到用户的加密数据,如:微信步数。
官方文档对此已提供了较为详细的解决方案,本文用 JavaScript 写请求与 NodeJS 写接口部署实践,希望让前端视角的小伙伴更能一目了然整体流程。
如果你是Java,官方文档也提供了各种语言的解密算法:
https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html#方式一:开发者后台校验与解密开放数据
02 流程:
1. 前端调用 wx.login 登录拿到 code
2. 前端调用 code2Session 接口获取 openid,session_key。
此处后端通过小程序运营后台的 appid,secret 及前端传来的 code 调用微信 sdk 获取 openid,session_key并返回
app.post('/code2Session', (req, res)=>{
const result = {data: {}};
if(!req.body?.code) {
result.msg = `缺少登录获取的code参数`;
result.code = '0';
return res.json(result);
}
const url = `https://api.weixin.qq.com/sns/jscode2session?appid=${appid}&secret=${secret}&js_code=${req.body.code}&grant_type=authorization_code`;
const options = {
headers: {}
};
https.get(url, options, httpsres => {
httpsres.setEncoding('utf8');
// 监听返回的数据
httpsres.on('data', (data) => {
result.msg = `success`;
result.code = '200';
result.data = data;
});
// 监听接口请求完成, 除非error,最终都会执行end;
httpsres.on('end', () => {
return res.json(result);
});
}).on('error', err => {
result.msg = `getToken失败————${err}`;
result.code = '0';
return res.json(result);
});
})
3. 前端拿到openid,session_key存储供后续使用
4. 前端调用解密接口获取解密数据
此处后端通过前端传递的 sessionKey,encryptedData,iv 调用官方提供的解密算法并返回数据
注:前端调用敏感数据API时,会拿到加密数据 encryptedData,加密算法的初始向量 iv
app.post('/decode', (req, res)=>{
const result = {data: {}};
const { sessionKey='', encryptedData='', iv='' } = req.body;
if(!(sessionKey && encryptedData && iv)) {
result.msg = `必要参数sessionKey, encryptedData, iv`;
result.code = '0';
return res.json(result);
}
const pc = new WXBizDataCrypt(appid, sessionKey);
result.msg = `success`;
result.code = '200';
result.data = pc.decryptData(encryptedData , iv);
return res.json(result);
})
示例:node解密算法如下
function WXBizDataCrypt(appid, sessionKey) {
this.appid = appid
this.sessionKey = sessionKey
}
WXBizDataCrypt.prototype.decryptData = function (encryptedData, iv) {
// base64 decode
var sessionKey = new Buffer(this.sessionKey, 'base64')
encryptedData = new Buffer(encryptedData, 'base64')
iv = new Buffer(iv, 'base64')
try {
// 解密
var decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, iv)
// 设置自动 padding 为 true,删除填充补位
decipher.setAutoPadding(true)
var decoded = decipher.update(encryptedData, 'binary', 'utf8')
decoded += decipher.final('utf8')
decoded = JSON.parse(decoded)
} catch (err) {
throw new Error('Illegal Buffer1')
}
if (decoded.watermark.appid !== this.appid) {
throw new Error('Illegal Buffer2')
}
return decoded
}