• 前端请求参数MD5加密校验,参数串解密


    首先引入MD5加密库:=>https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js;

      步骤:=》1.请求前对参数进行字典升序排序,排序函数 

    function objKeySort(obj) {
    var newkey = Object.keys(obj).sort();
    //先用Object内置类的keys方法获取要排序对象的属性名,再利用Array原型上的sort方法对获取的属性名进行排序,newkey是一个数组
    var newObj = {};//创建一个新的对象,用于存放排好序的键值对
    for (var i = 0; i < newkey.length; i++) {//遍历newkey数组
    newObj[newkey[i]] = obj[newkey[i]];//向新创建的对象中按照排好的顺序依次增加键值对
    }
    return newObj;//返回排好序的新对象
    }

          2.排序后对参数进行校验,校验参数涉及签名的请求头=》

    oncekey 客户端生成临时随机数6-8位字母或数字
    timestr timestr时间戳
    signkey 请求签名key
    wxsmall 对随机生成的oncekeyMD5

          并将oncekey 与timestr连接进行MD5,获得hash字符串 将hash与datastr连接进行md5,datastr需引用函数objtostring将其转化为字符串,得到签名signkey,校验签名函数+字符串转化函数objtostring:    

    function signrequest
    (data) {
    data = objKeySort(data);//请求参数排序
    var staticstr = '';
    var timestr = parseInt((new Date()).getTime() / 1000);
    var oncekey = parseInt(Math.random() * (100000 - 1000 + 1) + 1000, 10);
    var wxsmall = md5(oncekey);
    console.log("wxsmall:" + wxsmall);
    var hash = md5(md5(wxsmall + '' + oncekey));
    console.log("hash:" + hash);
    var datastr = objtostring(data);
    console.log("hash+datastr:" + hash + datastr);
    var sign = md5(hash + datastr);
    return { "timestr": timestr, "oncekey": oncekey, "wxsmall": wxsmall, "signkey": sign };
    }
     
    function objtostring(data) {//Object to String
    var str = '';
    for (var k in data) {
    str += k + '=' + encodeURI(data[k]) + '&';
    }
    if (str) {
    str = str.substring(str, str.length - 1);
    }
    return str;
    }
    3.数据解密规则:
    • 对签名通过后返回的data加密串signdata进行base64解码,得到Base64后的串,Base64解码函数decode=>
    • function  decode(input) {
      var output = "";
      var chr1, chr2, chr3;
      var enc1, enc2, enc3, enc4;
      var i = 0;
      input = input.replace(/[^A-Za-z0-9+/=]/g, "");
      while (i < input.length) {
      enc1 = _keyStr.indexOf(input.charAt(i++));
      enc2 = _keyStr.indexOf(input.charAt(i++));
      enc3 = _keyStr.indexOf(input.charAt(i++));
      enc4 = _keyStr.indexOf(input.charAt(i++));
      chr1 = (enc1 << 2) | (enc2 >> 4);
      chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
      chr3 = ((enc3 & 3) << 6) | enc4;
      output = output + String.fromCharCode(chr1);
      if (enc3 != 64) {
      output = output + String.fromCharCode(chr2);
      }
      if (enc4 != 64) {
      output = output + String.fromCharCode(chr3);
      }
      }
      output = _utf8_decode(output);
      return output;
      }
      // private method for UTF-8 decoding
      var _utf8_decode = function (utftext) {
      var string = "";
      var i = 0;
      var c = 0,
      c1 = 0,
      c2 = 0,
      c3 = 0;
      while (i < utftext.length) {
      c = utftext.charCodeAt(i);
      if (c < 128) {
      string += String.fromCharCode(c);
      i++;
      } else if ((c > 191) && (c < 224)) {
      c2 = utftext.charCodeAt(i + 1);
      string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
      i += 2;
      } else {
      c2 = utftext.charCodeAt(i + 1);
      c3 = utftext.charCodeAt(i + 2);
      string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
      i += 3;
      }
      }
      return string;
      }
    • 截取BASE64串string长度-4后进行MD5,并对MD5后的字符串截取长度15的串,将该串与BASE64串string长度-4后的串进行异或运算得到解密后的data字符串=>
    • function responseencode(data, apiSignModel) {//data => encode string
      var isencode = 0;
      isencode = apiSignModel;

      if (!isencode) {
      return data;
      }
      console.log("---callback-----data---encode--->", data);
      data = base64.decode(data);//encodeString

      var rand = data.substring(data.length - 4);
      var md = md5(rand);
      var p = md.substring(0, 16);
      console.log("data " + data);
      console.log("rand " + rand);
      data = data.substring(0, data.length - 4);
      data = strox(data, p);
      console.log("p " + p);
      return data;
      }

     其中apiSignModel就是responseHeader返回的API-SIGN-MODAL,客户端可以根据该返回参数决定是否对返回的数据串 解密,异或运算是为了得到经过一次异或运算之前的初始加密串,字符串在经过两次异或运算会得到原始的数据,参考https://www.lijinma.com/blog/2014/05/29/amazing-xor/,异或匀速算实现函数=>

    function strox(str, orstr) {
    var result = [];
    var len = orstr.length;

    for (var i = 0; i < str.length; i++) {
    var item = str[i];
    var strcode = parseInt(item.charCodeAt().toString(10));
    var orcode = parseInt(orstr[i % len].charCodeAt().toString(10));
    var rescode = strcode ^ orcode;
    var binaryStr = String.fromCharCode(rescode);
    result.push(binaryStr);
    }
    return result.join("");
    }
    简单来说,异或运算函数是将两个参数1和2相加进行异或得到3,再次异或运算后可将3和1进行异或就可以得出异或前的数字2.整体代码封装一下就是这样:
    import md5 from './md5-support.js';
    var Base64 = function () {

    // private property
    var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    // public method for decoding
    this.decode = function (input) {
    var output = "";
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;
    input = input.replace(/[^A-Za-z0-9+/=]/g, "");
    while (i < input.length) {
    enc1 = _keyStr.indexOf(input.charAt(i++));
    enc2 = _keyStr.indexOf(input.charAt(i++));
    enc3 = _keyStr.indexOf(input.charAt(i++));
    enc4 = _keyStr.indexOf(input.charAt(i++));
    chr1 = (enc1 << 2) | (enc2 >> 4);
    chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
    chr3 = ((enc3 & 3) << 6) | enc4;
    output = output + String.fromCharCode(chr1);
    if (enc3 != 64) {
    output = output + String.fromCharCode(chr2);
    }
    if (enc4 != 64) {
    output = output + String.fromCharCode(chr3);
    }
    }
    output = _utf8_decode(output);
    return output;
    }

    // private method for UTF-8 decoding
    var _utf8_decode = function (utftext) {
    var string = "";
    var i = 0;
    var c = 0,
    c1 = 0,
    c2 = 0,
    c3 = 0;
    while (i < utftext.length) {
    c = utftext.charCodeAt(i);
    if (c < 128) {
    string += String.fromCharCode(c);
    i++;
    } else if ((c > 191) && (c < 224)) {
    c2 = utftext.charCodeAt(i + 1);
    string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
    i += 2;
    } else {
    c2 = utftext.charCodeAt(i + 1);
    c3 = utftext.charCodeAt(i + 2);
    string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
    i += 3;
    }
    }
    return string;
    }
    }

    var Apisecure = function () {
    var base64 = new Base64();
    function strox(str, orstr) {
    var result = [];
    var len = orstr.length;

    for (var i = 0; i < str.length; i++) {
    var item = str[i];
    var strcode = parseInt(item.charCodeAt().toString(10));
    var orcode = parseInt(orstr[i % len].charCodeAt().toString(10));
    var rescode = strcode ^ orcode;
    var binaryStr = String.fromCharCode(rescode);
    result.push(binaryStr);
    }
    return result.join("");
    }

    function objtostring(data) {
    var str = '';
    for (var k in data) {
    str += k + '=' + encodeURI(data[k]) + '&';
    }
    if (str) {
    str = str.substring(str, str.length - 1);
    }
    return str;
    }


    function objKeySort(obj) {//排序的函数
    var newkey = Object.keys(obj).sort();
    //先用Object内置类的keys方法获取要排序对象的属性名,再利用Array原型上的sort方法对获取的属性名进行排序,newkey是一个数组
    var newObj = {};//创建一个新的对象,用于存放排好序的键值对
    for (var i = 0; i < newkey.length; i++) {//遍历newkey数组
    newObj[newkey[i]] = obj[newkey[i]];//向新创建的对象中按照排好的顺序依次增加键值对
    }
    return newObj;//返回排好序的新对象
    }


    this.signrequest = function (data) {
    data = objKeySort(data);//请求参数排序
    var staticstr = '';
    var timestr = parseInt((new Date()).getTime() / 1000);
    var oncekey = parseInt(Math.random() * (100000 - 1000 + 1) + 1000, 10);
    var wxsmall = md5(oncekey);
    console.log("wxsmall:" + wxsmall);
    var hash = md5(md5(wxsmall + '' + oncekey));
    console.log("hash:" + hash);
    var datastr = objtostring(data);
    console.log("hash+datastr:" + hash + datastr);
    var sign = md5(hash + datastr);
    return { "timestr": timestr, "oncekey": oncekey, "wxsmall": wxsmall, "signkey": sign };
    }

    this.responseencode = function (data, apiSignModel) {//data => encode string
    var isencode = 0;
    isencode = apiSignModel;

    if (!isencode) {
    return data;
    }
    console.log("---callback-----data---encode--->", data);
    data = base64.decode(data);//encodeString

    var rand = data.substring(data.length - 4);
    var md = md5(rand);
    var p = md.substring(0, 16);
    console.log("data " + data);
    console.log("rand " + rand);
    data = data.substring(0, data.length - 4);
    data = strox(data, p);
    console.log("p " + p);
    return data;
    }

    }
    module.exports = {
    Base64,
    Apisecure
    }
    最后附上小程序内封装的微信请求调用方法=>
     
  • 相关阅读:
    Python文件操作
    两个标签页定位第二个标签页元素时显示element not visible
    Selenium Webdriver元素定位的八种常用方式
    Python集合set
    Python 字典
    数据库存储过程
    打印1-100
    》》》 《类的多态》
    》》》《类的继承》
    》》》关于eclipse中git同步代码报错checkout conflict with files的解决方法
  • 原文地址:https://www.cnblogs.com/lpggo/p/8316295.html
Copyright © 2020-2023  润新知