ShortURL.php 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. <?php
  2. /**
  3. * class ShortURL
  4. * usage:
  5. *
  6. * \Qii\Library\ShortURL::build($url);
  7. */
  8. namespace Qii\Library;
  9. class ShortURL {
  10. static $chars = [ "a" , "b" , "c" , "d" , "e" , "f" , "g" , "h" ,
  11. "i" , "j" , "k" , "l" , "m" , "n" , "o" , "p" , "q" , "r" , "s" , "t" ,
  12. "u" , "v" , "w" , "x" , "y" , "z" , "0" , "1" , "2" , "3" , "4" , "5" ,
  13. "6" , "7" , "8" , "9" , "A" , "B" , "C" , "D" , "E" , "F" , "G" , "H" ,
  14. "I" , "J" , "K" , "L" , "M" , "N" , "O" , "P" , "Q" , "R" , "S" , "T" ,
  15. "U" , "V" , "W" , "X" , "Y" , "Z"
  16. ];
  17. static $secKey = 'sU0dl';
  18. public static function build($url){
  19. if($url == null){
  20. return null ;
  21. }
  22. $group = [];
  23. //先得到url的32个字符的md5码
  24. $md5 = md5($url);
  25. //将32个字符的md5码分成4段处理,每段8个字符
  26. for ($i = 0; $i < 4 ; $i++) {
  27. $offset = i * 8 ;
  28. $sub = substr($md5, $offset, $offset + 8);
  29. $sub16 = base_convert($sub, 16, 10); //将sub当作一个16进制的数,转成long
  30. // & 0X3FFFFFFF,去掉最前面的2位,只留下30位
  31. $sub16 &= 0X3FFFFFFF ;
  32. $shortURL = '';
  33. //将剩下的30位分6段处理,每段5位
  34. for ($j = 0; $j < 6 ; $j++) {
  35. //得到一个 <= 61的数字
  36. $t = $sub16 & 0x0000003D;
  37. $shortURL .= self::$chars[$t] ;
  38. $sub16 >>= 5 ; //将sub16右移5位
  39. }
  40. return self::sign($shortURL);
  41. }
  42. return null ;
  43. }
  44. /**
  45. * 对生成的短链 key 进行签名
  46. */
  47. public static function sign($str)
  48. {
  49. $sign = md5(self::$secKey . $str);
  50. return $str . substr($sign, 8, 2);
  51. }
  52. /**
  53. * 验证生成的URL是否正确
  54. * @param string $str URL 串
  55. * @return bool
  56. */
  57. public static function verify($str)
  58. {
  59. $urlSign = substr($str, -2);
  60. $str = substr($str, 0, -2);
  61. $sign = md5(self::$secKey . $str);
  62. if(substr($sign, 8, 2) !== $urlSign) return false;
  63. return true;
  64. }
  65. }