微学网

热门关键词:   as  thinkphp  ecshop  xxx  商务通  php分页
热门: ASP.NET PHP编程 ASP编程 JSP编程 Python

ThinkPHP根据用户ID生成不重复的6位邀请码(使用Hashids实现,带解码方法)

发布时间:2020-04-21 来源:未知 点击:

什么是hashids?

Hashids是一个能利用整数生成出短小、唯一、非连续标识符的类库,它支持包含php在内的多种语言。Hashids支持通过生成出来的标识符进行解码为原数字,还支持加盐加密,不会因为大家都用这个类库就被猜到真实ID。

hashids的原理:

数字经过一个加盐(salted)算法产生一个哈希(hash)字符串。这样算法就是通过混淆使结果具有不可预测性,而唯一性依然由数字本身来达成,从而得到(类似 youtube 里的)足够短,不可预测且唯一的 ID。

第一步、创建Hashids.class.php类文件,在App\Home\Common目录下:

Hashids.class.php的代码如下:


  1.  
    <?php
  2.  
    namespace Home\Common;//自定义命名空间,要求模块名\文件夹名字方式。(需要放在第一行)
  3.  
    /*
  4.  
     
  5.  
    Hashids
  6.  
    http://hashids.org/php
  7.  
    (c) 2013 Ivan Akimov
  8.  
     
  9.  
    https://github.com/ivanakimov/hashids.php
  10.  
    hashids may be freely distributed under the MIT license.
  11.  
     
  12.  
    */
  13.  
     
  14.  
    /**
  15.  
    * HashGenerator is a contract for generating hashes
  16.  
    */
  17.  
    interface HashGenerator {
  18.  
     
  19.  
    /**
  20.  
    * Encodes a variable number of parameters to generate a hash
  21.  
    *
  22.  
    * @param mixed ...
  23.  
    *
  24.  
    * @return string the generated hash
  25.  
    */
  26.  
    public function encode();
  27.  
     
  28.  
    /**
  29.  
    * Decodes a hash to the original parameter values
  30.  
    *
  31.  
    * @param string $hash the hash to decode
  32.  
    *
  33.  
    * @return array
  34.  
    */
  35.  
    public function decode($hash);
  36.  
     
  37.  
    /**
  38.  
    * Encodes hexadecimal values to generate a hash
  39.  
    *
  40.  
    * @param string $str hexadecimal string
  41.  
    *
  42.  
    * @return string the generated hash
  43.  
    */
  44.  
    public function encode_hex($str);
  45.  
     
  46.  
    /**
  47.  
    * Decodes hexadecimal hash
  48.  
    *
  49.  
    * @param string $hash
  50.  
    *
  51.  
    * @return string hexadecimal string
  52.  
    */
  53.  
    public function decode_hex($hash);
  54.  
     
  55.  
    }
  56.  
     
  57.  
    class Hashids implements HashGenerator {
  58.  
     
  59.  
    const VERSION = '1.0.5';
  60.  
     
  61.  
    /* internal settings */
  62.  
     
  63.  
    const MIN_ALPHABET_LENGTH = 16;
  64.  
    const SEP_DIV = 3.5;
  65.  
    const GUARD_DIV = 12;
  66.  
     
  67.  
    /* error messages */
  68.  
     
  69.  
    const E_ALPHABET_LENGTH = 'alphabet must contain at least %d unique characters';
  70.  
    const E_ALPHABET_SPACE = 'alphabet cannot contain spaces';
  71.  
     
  72.  
    /* set at constructor */
  73.  
     
  74.  
    private $_alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
  75.  
    private $_seps = 'cfhistuCFHISTU';
  76.  
    private $_min_hash_length = 0;
  77.  
    private $_math_functions = array();
  78.  
    private $_max_int_value = 1000000000;
  79.  
     
  80.  
    const hashids_length = 6; // 加密字符串长度
  81.  
    const hashids_salt = 'test'; // 加密钥匙
  82.  
    const hashids_alphabet = ''; // 字符仓库,不填写默认为扩展里的字符仓库
  83.  
     
  84.  
    private static $instance; //单例
  85.  
     
  86.  
    /**
  87.  
    * 初始化
  88.  
    * @param array $options
  89.  
    * @return static
  90.  
    */
  91.  
    public static function instance($length = null, $salt = null, $alphabet = null)
  92.  
    {
  93.  
    if (is_null(self::$instance)) {
  94.  
    if ($length === null) $length = self::hashids_length;
  95.  
    if ($salt === null) $salt = self::hashids_salt;
  96.  
    if ($alphabet === null) self::hashids_alphabet;
  97.  
     
  98.  
    self::$instance = new static($salt, $length, $alphabet);
  99.  
    }
  100.  
    return self::$instance;
  101.  
    }
  102.  
     
  103.  
    public function __construct($salt = '', $min_hash_length = 8, $alphabet = '') {
  104.  
     
  105.  
    /* if either math precision library is present, raise $this->_max_int_value */
  106.  
     
  107.  
    if (function_exists('gmp_add')) {
  108.  
    $this->_math_functions['add'] = 'gmp_add';
  109.  
    $this->_math_functions['div'] = 'gmp_div';
  110.  
    $this->_math_functions['str'] = 'gmp_strval';
  111.  
    } else if (function_exists('bcadd')) {
  112.  
    $this->_math_functions['add'] = 'bcadd';
  113.  
    $this->_math_functions['div'] = 'bcdiv';
  114.  
    $this->_math_functions['str'] = 'strval';
  115.  
    }
  116.  
     
  117.  
    $this->_lower_max_int_value = $this->_max_int_value;
  118.  
    if ($this->_math_functions) {
  119.  
    $this->_max_int_value = PHP_INT_MAX;
  120.  
    }
  121.  
     
  122.  
    /* handle parameters */
  123.  
     
  124.  
    $this->_salt = $salt;
  125.  
     
  126.  
    if ((int)$min_hash_length > 0) {
  127.  
    $this->_min_hash_length = (int)$min_hash_length;
  128.  
    }
  129.  
     
  130.  
    if ($alphabet) {
  131.  
    $this->_alphabet = implode('', array_unique(str_split($alphabet)));
  132.  
    }
  133.  
     
  134.  
    if (strlen($this->_alphabet) < self::MIN_ALPHABET_LENGTH) {
  135.  
    throw new \Exception(sprintf(self::E_ALPHABET_LENGTH, self::MIN_ALPHABET_LENGTH));
  136.  
    }
  137.  
     
  138.  
    if (is_int(strpos($this->_alphabet, ' '))) {
  139.  
    throw new \Exception(self::E_ALPHABET_SPACE);
  140.  
    }
  141.  
     
  142.  
    $alphabet_array = str_split($this->_alphabet);
  143.  
    $seps_array = str_split($this->_seps);
  144.  
     
  145.  
    $this->_seps = implode('', array_intersect($alphabet_array, $seps_array));
  146.  
    $this->_alphabet = implode('', array_diff($alphabet_array, $seps_array));
  147.  
    $this->_seps = $this->_consistent_shuffle($this->_seps, $this->_salt);
  148.  
     
  149.  
    if (!$this->_seps || (strlen($this->_alphabet) / strlen($this->_seps)) > self::SEP_DIV) {
  150.  
     
  151.  
    $seps_length = (int)ceil(strlen($this->_alphabet) / self::SEP_DIV);
  152.  
     
  153.  
    if ($seps_length == 1) {
  154.  
    $seps_length++;
  155.  
    }
  156.  
     
  157.  
    if ($seps_length > strlen($this->_seps)) {
  158.  
     
  159.  
    $diff = $seps_length - strlen($this->_seps);
  160.  
    $this->_seps .= substr($this->_alphabet, 0, $diff);
  161.  
    $this->_alphabet = substr($this->_alphabet, $diff);
  162.  
     
  163.  
    } else {
  164.  
    $this->_seps = substr($this->_seps, 0, $seps_length);
  165.  
    }
  166.  
     
  167.  
    }
  168.  
     
  169.  
    $this->_alphabet = $this->_consistent_shuffle($this->_alphabet, $this->_salt);
  170.  
    $guard_count = (int)ceil(strlen($this->_alphabet) / self::GUARD_DIV);
  171.  
     
  172.  
    if (strlen($this->_alphabet) < 3) {
  173.  
    $this->_guards = substr($this->_seps, 0, $guard_count);
  174.  
    $this->_seps = substr($this->_seps, $guard_count);
  175.  
    } else {
  176.  
    $this->_guards = substr($this->_alphabet, 0, $guard_count);
  177.  
    $this->_alphabet = substr($this->_alphabet, $guard_count);
  178.  
    }
  179.  
     
  180.  
    }
  181.  
     
  182.  
    public function encode() {
  183.  
     
  184.  
    $ret = '';
  185.  
    $numbers = func_get_args();
  186.  
     
  187.  
    if (func_num_args() == 1 && is_array(func_get_arg(0))) {
  188.  
    $numbers = $numbers[0];
  189.  
    }
  190.  
     
  191.  
    if (!$numbers) {
  192.  
    return $ret;
  193.  
    }
  194.  
     
  195.  
    foreach ($numbers as $number) {
  196.  
     
  197.  
    $is_number = ctype_digit((string)$number);
  198.  
     
  199.  
    if (!$is_number || $number < 0 || $number > $this->_max_int_value) {
  200.  
    return $ret;
  201.  
    }
  202.  
     
  203.  
    }
  204.  
     
  205.  
    return $this->_encode($numbers);
  206.  
     
  207.  
    }
  208.  
     
  209.  
    public function decode($hash) {
  210.  
     
  211.  
    $ret = array();
  212.  
     
  213.  
    if (!$hash || !is_string($hash) || !trim($hash)) {
  214.  
    return $ret;
  215.  
    }
  216.  
     
  217.  
    return $this->_decode(trim($hash), $this->_alphabet);
  218.  
     
  219.  
    }
  220.  
     
  221.  
    public function encode_hex($str) {
  222.  
     
  223.  
    if (!ctype_xdigit((string)$str)) {
  224.  
    return '';
  225.  
    }
  226.  
     
  227.  
    $numbers = trim(chunk_split($str, 12, ' '));
  228.  
    $numbers = explode(' ', $numbers);
  229.  
     
  230.  
    foreach ($numbers as $i => $number) {
  231.  
    $numbers[$i] = hexdec('1' . $number);
  232.  
    }
  233.  
     
  234.  
    return call_user_func_array(array($this, 'encode'), $numbers);
  235.  
     
  236.  
    }
  237.  
     
  238.  
    public function decode_hex($hash) {
  239.  
     
  240.  
    $ret = "";
  241.  
    $numbers = $this->decode($hash);
  242.  
     
  243.  
    foreach ($numbers as $i => $number) {
  244.  
    $ret .= substr(dechex($number), 1);
  245.  
    }
  246.  
     
  247.  
    return $ret;
  248.  
     
  249.  
    }
  250.  
     
  251.  
    public function get_max_int_value() {
  252.  
    return $this->_max_int_value;
  253.  
    }
  254.  
     
  255.  
    private function _encode(array $numbers) {
  256.  
     
  257.  
    $alphabet = $this->_alphabet;
  258.  
    $numbers_size = sizeof($numbers);
  259.  
    $numbers_hash_int = 0;
  260.  
     
  261.  
    foreach ($numbers as $i => $number) {
  262.  
    $numbers_hash_int += ($number % ($i + 100));
  263.  
    }
  264.  
     
  265.  
    $lottery = $ret = $alphabet[$numbers_hash_int % strlen($alphabet)];
  266.  
    foreach ($numbers as $i => $number) {
  267.  
     
  268.  
    $alphabet = $this->_consistent_shuffle($alphabet, substr($lottery . $this->_salt . $alphabet, 0, strlen($alphabet)));
  269.  
    $ret .= $last = $this->_hash($number, $alphabet);
  270.  
     
  271.  
    if ($i + 1 < $numbers_size) {
  272.  
    $number %= (ord($last) + $i);
  273.  
    $seps_index = $number % strlen($this->_seps);
  274.  
    $ret .= $this->_seps[$seps_index];
  275.  
    }
  276.  
     
  277.  
    }
  278.  
     
  279.  
    if (strlen($ret) < $this->_min_hash_length) {
  280.  
     
  281.  
    $guard_index = ($numbers_hash_int + ord($ret[0])) % strlen($this->_guards);
  282.  
     
  283.  
    $guard = $this->_guards[$guard_index];
  284.  
    $ret = $guard . $ret;
  285.  
     
  286.  
    if (strlen($ret) < $this->_min_hash_length) {
  287.  
     
  288.  
    $guard_index = ($numbers_hash_int + ord($ret[2])) % strlen($this->_guards);
  289.  
    $guard = $this->_guards[$guard_index];
  290.  
     
  291.  
    $ret .= $guard;
  292.  
     
  293.  
    }
  294.  
     
  295.  
    }
  296.  
     
  297.  
    $half_length = (int)(strlen($alphabet) / 2);
  298.  
    while (strlen($ret) < $this->_min_hash_length) {
  299.  
     
  300.  
    $alphabet = $this->_consistent_shuffle($alphabet, $alphabet);
  301.  
    $ret = substr($alphabet, $half_length) . $ret . substr($alphabet, 0, $half_length);
  302.  
     
  303.  
    $excess = strlen($ret) - $this->_min_hash_length;
  304.  
    if ($excess > 0) {
  305.  
    $ret = substr($ret, $excess / 2, $this->_min_hash_length);
  306.  
    }
  307.  
     
  308.  
    }
  309.  
     
  310.  
    return $ret;
  311.  
     
  312.  
    }
  313.  
     
  314.  
    private function _decode($hash, $alphabet) {
  315.  
     
  316.  
    $ret = array();
  317.  
     
  318.  
    $hash_breakdown = str_replace(str_split($this->_guards), ' ', $hash);
  319.  
    $hash_array = explode(' ', $hash_breakdown);
  320.  
     
  321.  
    $i = 0;
  322.  
    if (sizeof($hash_array) == 3 || sizeof($hash_array) == 2) {
  323.  
    $i = 1;
  324.  
    }
  325.  
     
  326.  
    $hash_breakdown = $hash_array[$i];
  327.  
    if (isset($hash_breakdown[0])) {
  328.  
     
  329.  
    $lottery = $hash_breakdown[0];
  330.  
    $hash_breakdown = substr($hash_breakdown, 1);
  331.  
     
  332.  
    $hash_breakdown = str_replace(str_split($this->_seps), ' ', $hash_breakdown);
  333.  
    $hash_array = explode(' ', $hash_breakdown);
  334.  
     
  335.  
    foreach ($hash_array as $sub_hash) {
  336.  
    $alphabet = $this->_consistent_shuffle($alphabet, substr($lottery . $this->_salt . $alphabet, 0, strlen($alphabet)));
  337.  
    $ret[] = (int)$this->_unhash($sub_hash, $alphabet);
  338.  
    }
  339.  
     
  340.  
    if ($this->_encode($ret) != $hash) {
  341.  
    $ret = array();
  342.  
    }
  343.  
     
  344.  
    }
  345.  
     
  346.  
    //修改为直接返回字符串
  347.  
    if(isset($ret[0])){
  348.  
    return $ret[0];
  349.  
    }else{
  350.  
    return false;
  351.  
    }
  352.  
     
  353.  
     
  354.  
    }
  355.  
     
  356.  
    private function _consistent_shuffle($alphabet, $salt) {
  357.  
     
  358.  
    if (!strlen($salt)) {
  359.  
    return $alphabet;
  360.  
    }
  361.  
     
  362.  
    for ($i = strlen($alphabet) - 1, $v = 0, $p = 0; $i > 0; $i--, $v++) {
  363.  
     
  364.  
    $v %= strlen($salt);
  365.  
    $p += $int = ord($salt[$v]);
  366.  
    $j = ($int + $v + $p) % $i;
  367.  
     
  368.  
    $temp = $alphabet[$j];
  369.  
    $alphabet[$j] = $alphabet[$i];
  370.  
    $alphabet[$i] = $temp;
  371.  
     
  372.  
    }
  373.  
     
  374.  
    return $alphabet;
  375.  
     
  376.  
    }
  377.  
     
  378.  
    private function _hash($input, $alphabet) {
  379.  
     
  380.  
    $hash = '';
  381.  
    $alphabet_length = strlen($alphabet);
  382.  
     
  383.  
    do {
  384.  
     
  385.  
    $hash = $alphabet[$input % $alphabet_length] . $hash;
  386.  
    if ($input > $this->_lower_max_int_value && $this->_math_functions) {
  387.  
    $input = $this->_math_functions['str']($this->_math_functions['div']($input, $alphabet_length));
  388.  
    } else {
  389.  
    $input = (int)($input / $alphabet_length);
  390.  
    }
  391.  
     
  392.  
    } while ($input);
  393.  
     
  394.  
    return $hash;
  395.  
     
  396.  
    }
  397.  
     
  398.  
    private function _unhash($input, $alphabet) {
  399.  
     
  400.  
    $number = 0;
  401.  
    if (strlen($input) && $alphabet) {
  402.  
     
  403.  
    $alphabet_length = strlen($alphabet);
  404.  
    $input_chars = str_split($input);
  405.  
     
  406.  
    foreach ($input_chars as $i => $char) {
  407.  
     
  408.  
    $pos = strpos($alphabet, $char);
  409.  
    if ($this->_math_functions) {
  410.  
    $number = $this->_math_functions['str']($this->_math_functions['add']($number, $pos * pow($alphabet_length, (strlen($input) - $i - 1))));
  411.  
    } else {
  412.  
    $number += $pos * pow($alphabet_length, (strlen($input) - $i - 1));
  413.  
    }
  414.  
     
  415.  
    }
  416.  
     
  417.  
    }
  418.  
     
  419.  
    return $number;
  420.  
     
  421.  
    }
  422.  
     
  423.  
    }

 第二步、在Controller控制器中引入Hashids类,并使用Hashids的类方法实现加解密操作。

1、引入Hashids类

2、实例化Hashids类,加解密


  1.  
    /*-----------------根据用户ID生成邀请码 start-----------------------------*/
  2.  
    //1.实例化Hashids类
  3.  
    $hashids=Hashids::instance(6,'mackie');//6为邀请码的长度,mackie为加盐密钥
  4.  
    //2.根据用户Id加密
  5.  
    $yqm=$hashids->encode(session('USER_KEY_ID'));
  6.  
    //3.反向解密
  7.  
    $id=$hashids->decode($yqm);
  8.  
    //4.输出到前台页面
  9.  
    $this->assign('yqm',$yqm);
  10.  
    $this->assign('id',$id);
  11.  
    $this->display();
  12.  
    /*-----------------根据用户ID生成邀请码 end------------------------------*/

3、最后我们看一下加解密的效果


这就是微学网-程序员之家为你提供的"ThinkPHP根据用户ID生成不重复的6位邀请码(使用Hashids实现,带解码方法)"希望对你有所帮助.本文来自网络,转载请注明出处:http://www.weixuecn.cn/article/14030.html
网络编程 | 前端制作 | 数据库 | CMS教程 | 脚本编程 | 框架 | 服务器 | 微信开发 | APP开发 |

凡本网站转载的文章、图片等资料的版权归版权所有人所有,因无法和版权所有者一一联系,如果本网站选取的文/图威胁到您的权益,请您及时和本网站联系。 我们会在第一时间内采取措施,避免给双方造 成不必要的损失。
© 2015-2018 微学网 版权所有,并保留所有权利。 备案号:粤ICP备09051474号-1

电脑版 | 移动版