用户密码登陆验证设计
今天在做用户登陆的时候,参考了以前学习和的教程,发现在用户登陆验证方面存在很大的漏洞,
网上教程大部份都是,简单的对用户数据加密然后存放到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;
}