php中通过Hashids将整数转化为唯一字符串
这个类主要是前台显示的主键ID转化成一串无规律的字符串,比较像 Youtube、Youku、Weibo之类的 id 名,从某种意义上可以防采集
在项目中,暴露给用户真实的项目ID,很有可能被恶意采集,很有可能被猜到目前有多少量(对造假不利)。
<?php /* Hashids
http://hashids.org/php
(c) 2013 Ivan Akimov https://github.com/ivanakimov/hashids.php
hashids may be freely distributed under the MIT license. */ /**
* HashGenerator is a contract for generating hashes
*/
interface HashGenerator { /**
* Encodes a variable number of parameters to generate a hash
*
* @param mixed ...
*
* @return string the generated hash
*/
public function encode(); /**
* Decodes a hash to the original parameter values
*
* @param string $hash the hash to decode
*
* @return array
*/
public function decode($hash); /**
* Encodes hexadecimal values to generate a hash
*
* @param string $str hexadecimal string
*
* @return string the generated hash
*/
public function encode_hex($str); /**
* Decodes hexadecimal hash
*
* @param string $hash
*
* @return string hexadecimal string
*/
public function decode_hex($hash); } class Hashids implements HashGenerator { const VERSION = '1.0.5'; /* internal settings */ const MIN_ALPHABET_LENGTH = 16;
const SEP_DIV = 3.5;
const GUARD_DIV = 12; /* error messages */ const E_ALPHABET_LENGTH = 'alphabet must contain at least %d unique characters';
const E_ALPHABET_SPACE = 'alphabet cannot contain spaces'; /* set at constructor */ private $_alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
private $_seps = 'cfhistuCFHISTU';
private $_min_hash_length = 0;
private $_math_functions = array();
private $_max_int_value = 1000000000; const hashids_length = 6; // 加密字符串长度
const hashids_salt = 'test'; // 加密钥匙
const hashids_alphabet = ''; // 字符仓库,不填写默认为扩展里的字符仓库 private static $instance; //单例 /**
* 初始化
* @param array $options
* @return static
*/
public static function instance($length = null, $salt = null, $alphabet = null)
{
if (is_null(self::$instance)) {
if ($length === null) $length = self::hashids_length;
if ($salt === null) $salt = self::hashids_salt;
if ($alphabet === null) self::hashids_alphabet; self::$instance = new static($salt, $length, $alphabet);
}
return self::$instance;
} public function __construct($salt = '', $min_hash_length = 8, $alphabet = '') { /* if either math precision library is present, raise $this->_max_int_value */ if (function_exists('gmp_add')) {
$this->_math_functions['add'] = 'gmp_add';
$this->_math_functions['div'] = 'gmp_div';
$this->_math_functions['str'] = 'gmp_strval';
} else if (function_exists('bcadd')) {
$this->_math_functions['add'] = 'bcadd';
$this->_math_functions['div'] = 'bcdiv';
$this->_math_functions['str'] = 'strval';
} $this->_lower_max_int_value = $this->_max_int_value;
if ($this->_math_functions) {
$this->_max_int_value = PHP_INT_MAX;
} /* handle parameters */ $this->_salt = $salt; if ((int)$min_hash_length > 0) {
$this->_min_hash_length = (int)$min_hash_length;
} if ($alphabet) {
$this->_alphabet = implode('', array_unique(str_split($alphabet)));
} if (strlen($this->_alphabet) < self::MIN_ALPHABET_LENGTH) {
throw new \Exception(sprintf(self::E_ALPHABET_LENGTH, self::MIN_ALPHABET_LENGTH));
} if (is_int(strpos($this->_alphabet, ' '))) {
throw new \Exception(self::E_ALPHABET_SPACE);
} $alphabet_array = str_split($this->_alphabet);
$seps_array = str_split($this->_seps); $this->_seps = implode('', array_intersect($alphabet_array, $seps_array));
$this->_alphabet = implode('', array_diff($alphabet_array, $seps_array));
$this->_seps = $this->_consistent_shuffle($this->_seps, $this->_salt); if (!$this->_seps || (strlen($this->_alphabet) / strlen($this->_seps)) > self::SEP_DIV) { $seps_length = (int)ceil(strlen($this->_alphabet) / self::SEP_DIV); if ($seps_length == 1) {
$seps_length++;
} if ($seps_length > strlen($this->_seps)) { $diff = $seps_length - strlen($this->_seps);
$this->_seps .= substr($this->_alphabet, 0, $diff);
$this->_alphabet = substr($this->_alphabet, $diff); } else {
$this->_seps = substr($this->_seps, 0, $seps_length);
} } $this->_alphabet = $this->_consistent_shuffle($this->_alphabet, $this->_salt);
$guard_count = (int)ceil(strlen($this->_alphabet) / self::GUARD_DIV); if (strlen($this->_alphabet) < 3) {
$this->_guards = substr($this->_seps, 0, $guard_count);
$this->_seps = substr($this->_seps, $guard_count);
} else {
$this->_guards = substr($this->_alphabet, 0, $guard_count);
$this->_alphabet = substr($this->_alphabet, $guard_count);
} } public function encode() { $ret = '';
$numbers = func_get_args(); if (func_num_args() == 1 && is_array(func_get_arg(0))) {
$numbers = $numbers[0];
} if (!$numbers) {
return $ret;
} foreach ($numbers as $number) { $is_number = ctype_digit((string)$number); if (!$is_number || $number < 0 || $number > $this->_max_int_value) {
return $ret;
} } return $this->_encode($numbers); } public function decode($hash) { $ret = array(); if (!$hash || !is_string($hash) || !trim($hash)) {
return $ret;
} return $this->_decode(trim($hash), $this->_alphabet); } public function encode_hex($str) { if (!ctype_xdigit((string)$str)) {
return '';
} $numbers = trim(chunk_split($str, 12, ' '));
$numbers = explode(' ', $numbers); foreach ($numbers as $i => $number) {
$numbers[$i] = hexdec('1' . $number);
} return call_user_func_array(array($this, 'encode'), $numbers); } public function decode_hex($hash) { $ret = "";
$numbers = $this->decode($hash); foreach ($numbers as $i => $number) {
$ret .= substr(dechex($number), 1);
} return $ret; } public function get_max_int_value() {
return $this->_max_int_value;
} private function _encode(array $numbers) { $alphabet = $this->_alphabet;
$numbers_size = sizeof($numbers);
$numbers_hash_int = 0; foreach ($numbers as $i => $number) {
$numbers_hash_int += ($number % ($i + 100));
} $lottery = $ret = $alphabet[$numbers_hash_int % strlen($alphabet)];
foreach ($numbers as $i => $number) { $alphabet = $this->_consistent_shuffle($alphabet, substr($lottery . $this->_salt . $alphabet, 0, strlen($alphabet)));
$ret .= $last = $this->_hash($number, $alphabet); if ($i + 1 < $numbers_size) {
$number %= (ord($last) + $i);
$seps_index = $number % strlen($this->_seps);
$ret .= $this->_seps[$seps_index];
} } if (strlen($ret) < $this->_min_hash_length) { $guard_index = ($numbers_hash_int + ord($ret[0])) % strlen($this->_guards); $guard = $this->_guards[$guard_index];
$ret = $guard . $ret; if (strlen($ret) < $this->_min_hash_length) { $guard_index = ($numbers_hash_int + ord($ret[2])) % strlen($this->_guards);
$guard = $this->_guards[$guard_index]; $ret .= $guard; } } $half_length = (int)(strlen($alphabet) / 2);
while (strlen($ret) < $this->_min_hash_length) { $alphabet = $this->_consistent_shuffle($alphabet, $alphabet);
$ret = substr($alphabet, $half_length) . $ret . substr($alphabet, 0, $half_length); $excess = strlen($ret) - $this->_min_hash_length;
if ($excess > 0) {
$ret = substr($ret, $excess / 2, $this->_min_hash_length);
} } return $ret; } private function _decode($hash, $alphabet) { $ret = array(); $hash_breakdown = str_replace(str_split($this->_guards), ' ', $hash);
$hash_array = explode(' ', $hash_breakdown); $i = 0;
if (sizeof($hash_array) == 3 || sizeof($hash_array) == 2) {
$i = 1;
} $hash_breakdown = $hash_array[$i];
if (isset($hash_breakdown[0])) { $lottery = $hash_breakdown[0];
$hash_breakdown = substr($hash_breakdown, 1); $hash_breakdown = str_replace(str_split($this->_seps), ' ', $hash_breakdown);
$hash_array = explode(' ', $hash_breakdown); foreach ($hash_array as $sub_hash) {
$alphabet = $this->_consistent_shuffle($alphabet, substr($lottery . $this->_salt . $alphabet, 0, strlen($alphabet)));
$ret[] = (int)$this->_unhash($sub_hash, $alphabet);
} if ($this->_encode($ret) != $hash) {
$ret = array();
} } //修改为直接返回字符串
if(isset($ret[0])){
return $ret[0];
}else{
return false;
} } private function _consistent_shuffle($alphabet, $salt) { if (!strlen($salt)) {
return $alphabet;
} for ($i = strlen($alphabet) - 1, $v = 0, $p = 0; $i > 0; $i--, $v++) { $v %= strlen($salt);
$p += $int = ord($salt[$v]);
$j = ($int + $v + $p) % $i; $temp = $alphabet[$j];
$alphabet[$j] = $alphabet[$i];
$alphabet[$i] = $temp; } return $alphabet; } private function _hash($input, $alphabet) { $hash = '';
$alphabet_length = strlen($alphabet); do { $hash = $alphabet[$input % $alphabet_length] . $hash;
if ($input > $this->_lower_max_int_value && $this->_math_functions) {
$input = $this->_math_functions['str']($this->_math_functions['div']($input, $alphabet_length));
} else {
$input = (int)($input / $alphabet_length);
} } while ($input); return $hash; } private function _unhash($input, $alphabet) { $number = 0;
if (strlen($input) && $alphabet) { $alphabet_length = strlen($alphabet);
$input_chars = str_split($input); foreach ($input_chars as $i => $char) { $pos = strpos($alphabet, $char);
if ($this->_math_functions) {
$number = $this->_math_functions['str']($this->_math_functions['add']($number, $pos * pow($alphabet_length, (strlen($input) - $i - 1))));
} else {
$number += $pos * pow($alphabet_length, (strlen($input) - $i - 1));
} } } return $number; } }
调用Hashids类进行加密解密ID
$user_id = 11;
$hashids = Hashids::instance(8,'test11');
$encode_id = $hashids->encode($user_id); //加密
echo '<pre>';
var_dump($encode_id).PHP_EOL;
$decode_id = $hashids->decode($encode_id); //解密
echo '<pre>';
var_dump($decode_id).PHP_EOL;
exit();
php中通过Hashids将整数转化为唯一字符串的更多相关文章
- Python如何将整数转化成二进制字符串
Python 如何将整数转化成二进制字符串 1.你可以自己写函数采用 %2 的方式来算. >>> binary = lambda n: '' if n==0 else binary( ...
- c++中二进制和整数转化
#1,包含文件 #include<bitset> #2,整数转化成二进制 int a = 63; bitset<6> bs(a); #3,二进制转化成整数 int b = bs ...
- [LeetCode] Integer to Roman 整数转化成罗马数字
Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 t ...
- c++实现atoi()和itoa()函数(字符串和整数转化)
(0) c++类型所占的字节和表示范围 c 语言里 类型转换那些事儿(补码 反码) 应届生面试准备之道 最值得学习阅读的10个C语言开源项目代码 一:起因 (1)字符串类型转化为整数型(Integer ...
- [LeetCode] 12. Integer to Roman 整数转化成罗马数字
Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M. Symbol Value I 1 ...
- [转载]JavaScript 中小数和大整数的精度丢失
标题: JavaScript 中小数和大整数的精度丢失作者: Demon链接: http://demon.tw/copy-paste/javascript-precision.html版权: 本博客的 ...
- javascript中的隐式类型转化
javascript中的隐式类型转化 #隐式转换 ## "+" 字符串和数字 如果某个操作数是字符串或者能够通过以下步骤转换为字符串的话,+将进行拼接操作. 如果其中一个操作数是对 ...
- C++中int与string的转化
C++中int与string的转化 int本身也要用一串字符表示,前后没有双引号,告诉编译器把它当作一个数解释.缺省情况下,是当成10进制(dec)来解释,如果想用8进制,16进制,怎么办?加上前缀, ...
- 《剑指Offer》第1题(Java实现):在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
一.题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该 ...
随机推荐
- [LeetCode] 849. Maximize Distance to Closest Person_Easy tag: BFS
In a row of seats, 1 represents a person sitting in that seat, and 0 represents that the seat is emp ...
- vue弹窗组件
文件结构 component.vue <template> <div class="_vuedals" v-show="show"> & ...
- MySQL数据类型--与MySQL零距离接触 3-2 外键约束的要求解析
列级约束:只针对某一个字段 表级约束:约束针对2个或2个以上的字段 约束类型是按功能来划分. 外键约束:保持数据一致性,完整性.实现数据表的一对一或一对多的关系.这就是把MySQL称为关系型数据库的根 ...
- MVC爬取网页指定内容到数据库
控制器 //获取并插入 //XPath获取 public JsonResult Add(string url) { HtmlWeb web = new HtmlWeb(); HtmlDocument ...
- Oracle推进SCN系列:使用oradebug在mount状态下推进SCN
环境:RHEL 6.5(x86-64) + Oracle 11.2.0.4 声明:推进SCN属于非常规恢复范畴,不建议非专业人员操作,否则后果自负. 需求:我这里演示下推进SCN 10W数量级,实际需 ...
- 12月centos单词
---恢复内容开始--- UNreachable:adj.(network server unreachable) 不能达到的; 及不到的; 取不到的; 不能得到的; rsync: rsync [re ...
- linux telnet命令
telnet命令通常用来远程登录.telnet程序是基于TELNET协议的远程登录客户端程序.Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式.它为用户 ...
- CSS笔记之Grid网格系统
Grid布局已经不是新鲜的技术了,但一直都是使用了Flex布局,如今需要了边学习边做些常用的笔记.首先grid和flex一样都不支持IE10以下的浏览器 基本布局: 一般是所有子元素都横向排列或者都纵 ...
- hibernate添加数据入门小案例
1.建立一个java项目,在目录下新建一个lib文件夹引入hibernate架包如图所示: 2. 新建com.LHB.domain包,在包中分别创建一个Employee.java和Employee.h ...
- Git SSH密钥对生成以及多个SSH存在情况配置
一.使用Git Bash 生成一个新的SSH密钥 1. 打开 Git Bash. 2. 邮箱设置粘贴下面的文字,替换成为你自己的邮箱. Github SSH 1 $ ssh-keygen -t rsa ...