用户密码登陆验证设计
今天在做用户登陆的时候,参考了以前学习和的教程,发现在用户登陆验证方面存在很大的漏洞,
网上教程大部份都是,简单的对用户数据加密然后存放到cookie中,来判用户是否已登陆,当别
人看到源码的加密方式后,通过在本地以同样的加密方法生成密文后,在通过修改浏览器cookie,
从而绕过验证直接进入你的网站后台!!!
以下是我重新设计的密方法
加密过程:----------------------------------------
/* * 变量注解: * $auth_key =rands(7); 7位随机数,用于解密 * $ip 用户ip地址 * $userId 用户id * $username 用户名 * $password = sha1('51zuso'.$password);用户密码 */ //自定义lock函数可逆加密 $auth_cookie = $ip."\t".$userId."\t".$userName."\t".$password,$auth_key; $auth_name = lock($auth_str,$auth_key); //生成浏览器cookie,有效时间2小时 cookie('auth_name',$auth_name,7200); cookie('auth_key',$auth_key,7200); //将cookie写入数据库,用于验证 db('auth')->where('id',$userId)->update(['cookie'=>$auth_cookie]); //生成缓存,用于快速验证 cache('userPass'.$userId,$auth_name,7200); //写入缓存,用于验证比对
解密过程----------------------------------------
//读取浏览器cookie $auth_name = cookie('auth_name'); $auth_key = cookie('auth_key'); //判断cookie是否存在 if($auth_name !='' && $auth_key != ''){ //验证不通过 return false; } //unlock自定义解密函数,解密cookie $auth_name_arr = explode("\t",unlock($auth_name,$auth_key)); $userId = $auth_name_arr[1]; //缓存快速验证,减少消耗 if(cache('userPass'.$userId) == $auth_name){ //验证通过 return true; }else{ //缓存验证不通过,有可能是缓存被管理员清除了,所有进行数据库验证 $cookie = db('auto')->where(['id'=>$userId])->value('cookie'); if($auth_name != '' && $auth_name == $cookie){ //验证通过 return true; }else{ //验证不通过 return false; } }
//用到的自定义函数,其它部份函数是用的是thinkphp5自带的----------------------------------------
//加密函数 function lock($txt,$key='www.51zuso.com'){ $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-=+"; $nh = rand(0,64); $ch = $chars[$nh]; $mdKey = md5($key.$ch); $mdKey = substr($mdKey,$nh%8, $nh%8+7); $txt = base64_encode($txt); $tmp = ''; $i=0;$j=0;$k = 0; for ($i=0; $i<strlen($txt); $i++) { $k = $k == strlen($mdKey) ? 0 : $k; $j = ($nh+strpos($chars,$txt[$i])+ord($mdKey[$k++]))%64; $tmp .= $chars[$j]; } return urlencode($ch.$tmp); } //解密函数 function unlock($txt,$key='www.51zuso.com'){ $txt = urldecode($txt); $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-=+"; $ch = $txt[0]; $nh = strpos($chars,$ch); $mdKey = md5($key.$ch); $mdKey = substr($mdKey,$nh%8, $nh%8+7); $txt = substr($txt,1); $tmp = ''; $i=0;$j=0; $k = 0; for ($i=0; $i<strlen($txt); $i++) { $k = $k == strlen($mdKey) ? 0 : $k; $j = strpos($chars,$txt[$i])-$nh - ord($mdKey[$k++]); while ($j<0) $j+=64; $tmp .= $chars[$j]; } return base64_decode($tmp); } //获取随机字符串函数 function rands($length){ $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; $code = ''; for ($i = 0; $i < $length; $i++) { $code .= $chars[ mt_rand(0, strlen($chars) - 1) ]; } return $code; }