PHP菜鸟博客_共同学习分享PHP技术心得【PHP爱好者】
js语言里面的加号什么时候是字符串拼接,什么时候运算符号呢
2022-10-1 菜鸟站长






事情发生在2022101号,刚刚放假,正在外面吃饭,突然接到客诉说小程序出问题了,提示签名不对。后端没有更新过接口,小程序也是好几个月没有更新了,为啥早上突然返回说出问题了呢?



先粘贴下代码,然后简单说下小程序调用接口的签名逻辑:



 



//发送数据给接口



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里面即可以是运算符的加法,也可以是字符串拼接。根据程序的直觉,这个第二个步骤应该是字符串拼接,不是加法。



先说为啥930号为啥没事。101号就突然崩溃了呢



2022+09+30 里面的09是个字符串不是数字,所以这个的结果是20220930



2022+10+01 这个的结果是2032012022+10js认为两个都是数字,所以是2032+01,又认为01是字符串,所以后半部分是字符串拼接,最终结果是203201,而这里服务端语言计算出来的是20221001,这里出现了偏差。



解决方案就是在+中间故意拼接一个空字符串,也就是让js强转字符串。当然也可以在拼接的最前面先拼接一个空字符串,这样后面怎么拼接都是字符串的拼接了就。



var msg_md5_2 = ””+year + mon + date + msg_md5_1.toUpperCase() + h + m + s;







最后结论:这个小程序只能在每年的01月份-09月份运行,超过10月份就签名错误了。










发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容