业务id转密文短链的一种实现思路

业务场景:

买家通过电商app下单后,会受到一条短信,短信内容中包括改订单详情页面的h5地址连接,因为是出现在短信中,所以对连接有要求:1.尽量短;2.安全性考虑,订单在数据库中对应的自增主键id不能暴露出来;3. url中id加密串位数要固定

解决思路:

  1. 要满足第2条要求,肯定是要对id进行某种加密后来展现到url中,其实方法有很多,可以通过把10进制id转为高进制(比如36进制)串;也可以直接对id进行md5加密。但是转换高进制的方式会位数不固定,这样不符合第3个条件。直接md5加密太长不满足条件2。鉴于此,要继续往下深入思考一下了

  2. 在搜索引擎如此发达的时代,如果什么事情都想着自己去原创,那样会显得太傻,于是,当你当前所能想出的方案不能解决问题时候,那就去度娘或者谷歌吧

  3. 于是去度娘敲下“微博短链”,深深可以借鉴,先粘上微博中url短链算法思路及代码如下:

    将长网址md5生成32位签名串,分为4段,每段8个字节;
    对这四段循环处理,取8个字节,将他看成16进制串与0x3fffffff(30位1)与操作,即超过30位的忽略处理;
    这30位分成6段,每5位的数字作为字母表的索引取得特定字符,依次进行获得6位字符串;
    总的md5串可以获得4个6位串;取里面的任意一个就可作为这个长url的短url地址;
    
    function shorturl($input) {
    $base32 = array ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h','i', 'j', 'k', 'l', 'm', 'n', 'o', 
    'p','q', 'r', 's', 't', 'u', 'v', 'w', 'x','y', 'z', '0', '1', '2', '3', '4', '5');
    $hex = md5($input);
    $hexLen = strlen($hex);
    $subHexLen = $hexLen / 8;
    $output = array();for ($i = 0; $i < $subHexLen; $i++) {
    $subHex = substr ($hex, $i * 8, 8);
    $int = 0x3FFFFFFF & (1 * ('0x'.$subHex));
    $out = '';for ($j = 0; $j < 6; $j++) {
        $val = 0x0000001F & $int;
        $out .= $base32[$val];
        $int = $int >> 5;
    }
    $output[] = $out;
    }return $output;
    }
  4. 看了之后,真是啧啧称赞,肯定就用这个思路了,但是需要稍稍改良一下,因为 这个加密后有6位,而我们要求5位,需要注意的事:要满足不同id加密后的唯一性(其实是尽量保持低碰撞率);他的短链可表示的连接数为32的6次方约等于10亿个,我们改成6位后至少也要可以表示这个量级。
    废话少说,修改后的算法如下:
    function shortUrl($id='', $salt='') {
    
    $base64 = array ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h','i', 'j', 'k', 'l', 'm', 'n', 'o', 
    'p','q', 'r', 's', 't', 'u', 'v', 'w', 'x','y', 'z', '0', '1', '2', '3', '4', '5','6', '7', '8', 
    '9', 'A', 'B', 'C', 'D','E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 
    'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 
    'U', 'V', 'W', 'X', 'Y', 'Z' );  
    $hex = md5($id.$salt);
    
    $hexLen = strlen($hex);
    
    $subHexLen = $hexLen / 8;
    
    $output = array();for ($i = 0; $i < $subHexLen; $i++) {
    
        $subHex = substr ($hex, $i * 8, 8); 
        $int = 0x3FFFFFFF & (1 * ('0x'.$subHex));
        $out = ''; 
        for ($j = 0; $j < 5; $j++) {
    
            $val = 0x0000003F & $int;
            $val = $val % 62; 
            $out .= $base64[$val];
            $int = $int >> 6;
        }   
        $output[] = $out;
    }
    $in = 0x3 & (1 * ('0x'.substr($hex, 0, 1)));return $output[$in];
    }
    

      

  

猜你喜欢

转载自www.cnblogs.com/aksir/p/9081687.html
今日推荐