js语言里面的加号什么时候是字符串拼接,什么时候运算符号呢
事情发生在2022年10月1号,刚刚放假,正在外面吃饭,突然接到客诉说小程序出问题了,提示签名不对。后端没有更新过接口,小程序也是好几个月没有更新了,为啥早上突然返回说出问题了呢?
先粘贴下代码,然后简单说下小程序调用接口的签名逻辑:
//发送数据给接口
function send_to_api(msg, resolve, reject, loading = "") {
var ActionTime = "";
var msg_md5_3 = "";
md5.getNow();
var myDate = new Date;
var year = myDate.getFullYear(); //获取当前年
var mon = md5.getNow(myDate.getMonth() + 1); //获取当前月
var date = md5.getNow(myDate.getDate()); //获取当前日
var h = md5.getNow(myDate.getHours()); //获取当前小时数(0-23)
var m = md5.getNow(myDate.getMinutes()); //获取当前分钟数(0-59)
var s = md5.getNow(myDate.getSeconds()); //获取当前秒
ActionTime = year + "-" + mon + "-" + date + " " + h + ":" + m + ":" + s;
var msg_md5_1 = md5.hex_md5(msg.toLowerCase());
//var msg_md5_2 = year + mon + date + msg_md5_1.toUpperCase() + h + m + s;
var msg_md5_2 = year + "" + mon + "" + date + "" + msg_md5_1.toUpperCase() + "" + h + "" + m + "" + s;
msg_md5_3 = md5.hex_md5(msg_md5_2).toUpperCase();
console.log('send msg', msg)
if (loading == "is_loading") {
wx.showLoading({
title: "加载中",
mask: true
});
}
wx.request({
url: api_url,
data: {
Msg: msg,
ActionK: msg_md5_3,
ActionTime: ActionTime
},
header: {
'custom-header': 'hello' //自定义请求头信息
},
success: function (res) {
console.log('get msg', res.data)
resolve(res)
},
fail: (err) => {
console.log('发送请求失败:', err)
reject(err)
},
complete: () => {
// 关闭正在等待的图标,在这里关闭,有些问题,挪到了具体调用的方法里去了
/*
if (loading == "is_loading") {
wx.hideLoading();
}*/
}
})
}
Msg这个可以理解为消息体内容也就是业务参数:
[{"Action":"get_wxmp_code_2","WxAppID":"wxae483b80c6dd01d2","code":"001z8RFa1ifMYD0LiwIa1WsMtz3z8RFe"}]
ActionTime: 2022-10-01 17:15:35
ActionK:理解为签名
这三个参数发送给接口,接口方获取到这三个参数,根据actionk是客户端时间,在获取服务器时间,两者做减法超过多长时间就认为客户端时间不正确,返回错误代码,然后是把获取到的消息体,根据事先和客户端协定的算法,计算出来一个字符串,判断客户去传过去的actionk和自己算出来是否一致,不一致就报错签名不对,证明数据被篡改过。
今天这次问题就出现在签名的计算上面了。下面说下签名的计算算法:
第一步:msg先转化为小写字母,然后在md5出来一个摘要,比如 ****
第二部:把这个摘要转化成大写,然后签名拼接年月日后面拼接时分秒。20221001***172930
第三步:然后在md5上面这个值,然后在转化成大写,得到最终的签名。AFA3348A692562B49F8CCED623246877
综上所述,意思就是消息体经过算法得到签名,运算中没有秘钥,但是签名算法不会被公开(客户端是小程序,如果是web那就不行了,web只能选择token,因为无论是算法还是秘钥都能被查询到),所以也能实现数据无法篡改的业务需求。
问题出现在第二步js的字符串拼接,+号惹的祸。哈哈分析下代码接下来:
var msg_md5_2 = year + mon + date + msg_md5_1.toUpperCase() + h + m + s;
这个加号在js里面即可以是运算符的加法,也可以是字符串拼接。根据程序的直觉,这个第二个步骤应该是字符串拼接,不是加法。
先说为啥9月30号为啥没事。10月1号就突然崩溃了呢
2022+09+30 里面的09是个字符串不是数字,所以这个的结果是20220930
2022+10+01 这个的结果是203201,2022+10,js认为两个都是数字,所以是2032+01,又认为01是字符串,所以后半部分是字符串拼接,最终结果是203201,而这里服务端语言计算出来的是20221001,这里出现了偏差。
解决方案就是在+中间故意拼接一个空字符串,也就是让js强转字符串。当然也可以在拼接的最前面先拼接一个空字符串,这样后面怎么拼接都是字符串的拼接了就。
var msg_md5_2 = ””+year + mon + date + msg_md5_1.toUpperCase() + h + m + s;
最后结论:这个小程序只能在每年的01月份-09月份运行,超过10月份就签名错误了。
版权声明:若无特殊注明,本文皆为《菜鸟站长》原创,转载请保留文章出处。
本文链接:js语言里面的加号什么时候是字符串拼接,什么时候运算符号呢 - https://wlphp.com/?post=371