云服务器 99 / 年,新老同享(可以99/年续费),开发者力荐特惠渠道,新客户在享受9折
阿里云推广

js语言里面的加号什么时候是字符串拼接,什么时候运算符号呢

  • 内容
  • 评论
  • 相关


事情发生在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月份就签名错误了。



本文标签:

版权声明:若无特殊注明,本文皆为《菜鸟站长》原创,转载请保留文章出处。

本文链接:js语言里面的加号什么时候是字符串拼接,什么时候运算符号呢 - https://wlphp.com/?post=371

发表评论

电子邮件地址不会被公开。 必填项已用*标注