diff --git a/admin/ajax.php b/admin/ajax.php index fab7ec6..70027dc 100644 --- a/admin/ajax.php +++ b/admin/ajax.php @@ -34,17 +34,20 @@ if ($_GET['mod'] === 'login'){ if ($verification !== true) { die(json_encode(array('code' => '-88', 'msg' => '请先进行人机验证'))); } - if (!$result = $db->select_first_row('sq_admin','*',array('username'=>$_POST['username'],'password'=>md5($_POST['password'])),'AND')){ - //$db->insert_back_id('sq_log_system',array('time'=>time(),'ip'=>get_real_ip(),'msg'=>'管理员 '.$_POST['username'].'使用密码'.$_POST['password'].'登陆失败:密码错误或账号不存在','type'=>'danger')); - $db->posterror('管理员登录尝试失败,账号['.$_POST['username'].']密码['.$_POST['password'].']','success'); + // P0-05: 按用户名取出后用 PHP 校验(兼容新 bcrypt / 旧 md5),成功即写回 bcrypt(惰性迁移); + // 失败日志不再记录明文密码(原 posterror 会把密码写入 sq_log_system) + $result = $db->select_first_row('sq_admin','*',array('username'=>$_POST['username']),'AND'); + if (!$result || !wq_verify_password($_POST['password'], $result['password'], 'md5')){ + $db->posterror('管理员登录尝试失败,账号['.$_POST['username'].']','danger'); die(json_encode(array('code' => -3, 'msg' => '输入的账号密码错误!'.$db->geterror()))); }else{ $_SESSION['admin_username'] = $_POST['username']; $_SESSION['admin_id'] = $result['ID']; $_SESSION['admin_qq'] = $result['qq']; - $_SESSION['admin_password'] = md5($_POST['password']); + $newhash = wq_hash_password($_POST['password']); + $_SESSION['admin_password'] = $newhash; $_SESSION['admin_HTTP_USER_AGENT'] = $_SERVER['HTTP_USER_AGENT']; - $db->update('sq_admin',array('username'=>$_SESSION['admin_username']),'AND',array('loginip'=>get_real_ip(),'logintime'=>time())); + $db->update('sq_admin',array('ID'=>$result['ID']),'AND',array('password'=>$newhash,'loginip'=>get_real_ip(),'logintime'=>time())); // $db->insert_back_id('sq_log_system',array('time'=>time(),'ip'=>get_real_ip(),'msg'=>'['.get_real_ip().']管理员 '.$_POST['username'].'使用密码登陆成功!','type'=>'success')); $db->posterror('管理员 '.$_POST['username'].'使用密码登录后台成功','success'); die(json_encode(array('code' => '1', 'msg' => '登陆成功,正在跳转!'))); @@ -491,6 +494,11 @@ switch ($_GET['mod']){ } + // P0-05: 用户密码改密以 bcrypt 哈希入库 + if ($_POST['mod'] == 'password') { + $_POST['value'] = wq_hash_password($_POST['value']); + } + if (!$db->update('sq_user',array('ID'=>$_POST['userid']),'AND',array($_POST['mod']=>$_POST['value']))){ die('修改失败'.$db->geterror()); }else{ @@ -624,7 +632,7 @@ switch ($_GET['mod']){ if ($db->select_first_row('sq_agent','*',array('username'=>$_POST['agent_name']),'AND') != false){ die('该代理账号已经存在,请尝试其他用户名'); } - if(!$db->insert_back_id('sq_agent',array('username'=>$_POST['agent_name'],'password'=>$_POST['agent_pass'],'money'=>$_POST['agent_money'],'levelid'=>$_POST['agent_leval'],'begintime'=>time(),'status'=>'1','loginip'=>'-','qq'=>$_POST['agent_qq']))){ + if(!$db->insert_back_id('sq_agent',array('username'=>$_POST['agent_name'],'password'=>wq_hash_password($_POST['agent_pass']),'money'=>$_POST['agent_money'],'levelid'=>$_POST['agent_leval'],'begintime'=>time(),'status'=>'1','loginip'=>'-','qq'=>$_POST['agent_qq']))){ die('添加失败:'.$db->geterror()); }else{ die('代理添加成功!'); @@ -674,11 +682,12 @@ switch ($_GET['mod']){ break; case 'getagentinfo': $result = $db->select_first_row('sq_agent','*',array('ID'=>$_POST['id']),'AND'); + // P0-05: 不再把密码(哈希或明文)回传前端;密码修改走 changeagent 单独入口 die(json_encode(array( 'agent_leval'=>$result['levelid'], 'agent_money'=>$result['money'], 'agent_name'=>$result['username'], - 'agent_pass'=>$result['password'] + 'agent_pass'=>'********' ))); break; @@ -695,6 +704,8 @@ switch ($_GET['mod']){ die('代理ID不能为空'); } if ($_POST['mod'] == 'status') $_POST['value'] = textbooltonum($_POST['value']); + // P0-05: 代理密码统一以 bcrypt 哈希入库 + if ($_POST['mod'] == 'password') $_POST['value'] = wq_hash_password($_POST['value']); if (!$db->update('sq_agent',array('ID'=>$_POST['aid']),'AND',array($_POST['mod']=>$_POST['value']))){ die('修改失败'.$db->geterror()); }else{ @@ -762,7 +773,7 @@ switch ($_GET['mod']){ if (empty($_POST['addusername']) || empty($_POST['adduserpass']) || empty($_POST['adduserqq'])){ die('数据不能为空,请检查'); } - $db->insert_back_id('sq_admin',array('username'=>$_POST['addusername'],'password'=>md5($_POST['adduserpass']),'qq'=>$_POST['adduserqq'])); + $db->insert_back_id('sq_admin',array('username'=>$_POST['addusername'],'password'=>wq_hash_password($_POST['adduserpass']),'qq'=>$_POST['adduserqq'])); die('管理员新增成功,如果需要删除请进数据库中的表sq_admin进行删除'); break; case 'sendtestmail': @@ -1050,11 +1061,12 @@ switch ($_GET['mod']){ if (!$agentinfo = $db->select_first_row('sq_admin','*',array('username'=>$_SESSION['admin_username']),'AND')){ die('管理员信息获取失败'); } - if (md5($_POST['oldpass']) !== $agentinfo['password']){ + // P0-05: 兼容校验旧 md5 / 新 bcrypt;新密码以 bcrypt 入库 + if (!wq_verify_password($_POST['oldpass'], $agentinfo['password'], 'md5')){ die('输入的原密码错误,无法修改!'); } - if(!$db->update('sq_admin',array('username'=>$_SESSION['admin_username']),'AND',array('password'=>md5($_POST['newpass'])))){ + if(!$db->update('sq_admin',array('username'=>$_SESSION['admin_username']),'AND',array('password'=>wq_hash_password($_POST['newpass'])))){ die('密码修改失败,服务器内部发生错误'); }else{ die('管理密码修改成功,请使用新密码进行登录!'); diff --git a/agent/ajax.php b/agent/ajax.php index eceb95e..7af053a 100644 --- a/agent/ajax.php +++ b/agent/ajax.php @@ -12,8 +12,9 @@ if ($_GET['mod'] === 'login') { if (!$result = $db->select_first_row('sq_agent', '*', array('accesstoken' => $_POST['token']), 'AND')) { die(json_encode(array('code' => '-1', 'msg' => '秘钥错误'))); } else { - $_SESSION['agent_username'] = $_POST['username']; - $_SESSION['agent_password'] = $_POST['password']; + $_SESSION['agent_username'] = $result['username']; + // P0-05: 会话持有数据库中的"存储值"(新 bcrypt / 旧明文),与重校验 WHERE password=会话 保持一致 + $_SESSION['agent_password'] = $result['password']; $_SESSION['agent_id'] = $result['ID']; $_SESSION['agent_qq'] = $result['qq']; $_SESSION['agent_HTTP_USER_AGENT'] = $_SERVER['HTTP_USER_AGENT']; @@ -35,18 +36,22 @@ if ($_GET['mod'] === 'login') { die(json_encode(array('code' => -2, 'msg' => '请输入您的密码'))); } - if (!$result = $db->select_first_row('sq_agent', '*', array('username' => $_POST['username'], 'password' => $_POST['password']), 'AND')) { + // P0-05: 按用户名取出后用 PHP 校验(兼容新 bcrypt / 旧明文),成功即写回 bcrypt(惰性迁移), + // 会话保存"存储值",保证 checklogin 重校验 WHERE password=会话 始终匹配 + $result = $db->select_first_row('sq_agent', '*', array('username' => $_POST['username']), 'AND'); + if (!$result || !wq_verify_password($_POST['password'], $result['password'])) { die(json_encode(array('code' => -3, 'msg' => '输入的账号密码错误!' . $db->geterror()))); } else { if ($result['status'] != '1') { die(json_encode(array('code' => -4, 'msg' => '代理账号已被冻结,请联系管理员或者上级处理'))); } + $newhash = wq_hash_password($_POST['password']); $_SESSION['agent_username'] = $_POST['username']; - $_SESSION['agent_password'] = $_POST['password']; + $_SESSION['agent_password'] = $newhash; $_SESSION['agent_id'] = $result['ID']; $_SESSION['agent_qq'] = $result['qq']; $_SESSION['agent_HTTP_USER_AGENT'] = $_SERVER['HTTP_USER_AGENT']; - $db->update('sq_agent', array('username' => $_SESSION['agent_username']), 'AND', array('loginip' => get_real_ip(), 'logintime' => time())); + $db->update('sq_agent', array('ID' => $result['ID']), 'AND', array('password' => $newhash, 'loginip' => get_real_ip(), 'logintime' => time())); die(json_encode(array('code' => '1', 'msg' => '登陆成功,正在跳转!'))); } @@ -296,6 +301,10 @@ switch ($_GET['mod']) { if ($_POST['mod'] == 'status') { $_POST['value'] = textbooltonum($_POST['value']); } + // P0-05: 用户密码以 bcrypt 哈希入库 + if ($_POST['mod'] == 'password') { + $_POST['value'] = wq_hash_password($_POST['value']); + } if ($_POST['mod'] == 'balance') { if ($_POST['value'] == '永久使用') { $_POST['value'] = -1; @@ -309,6 +318,11 @@ switch ($_GET['mod']) { } + // P0-05: 用户密码改密以 bcrypt 哈希入库 + if ($_POST['mod'] == 'password') { + $_POST['value'] = wq_hash_password($_POST['value']); + } + if (!$db->update('sq_user', array('ID' => $_POST['userid'], 'aid' => $_SESSION['agent_id']), 'AND', array($_POST['mod'] => $_POST['value']))) { die('修改失败' . $db->geterror()); } else { @@ -436,7 +450,8 @@ switch ($_GET['mod']) { 'tradeno' => $tradno, 'begintime' => $time, 'user' => $_POST['kt_user'], - 'pass' => $_POST['kt_pass'], + // P0-05: 订单中的密码直接以 bcrypt 哈希存库(开通落库点 function_auth 有幂等保护,不会二次哈希) + 'pass' => wq_hash_password($_POST['kt_pass']), 'fid' => $_POST['id'], 'num' => $_POST['kt_num'], 'paymoney' => $spendmoney, @@ -819,7 +834,7 @@ switch ($_GET['mod']) { if (!$db->update('sq_agent', array('username' => $_SESSION['agent_username']), 'AND', array('money' => $newmoney))) { die('系统内部错误,开通失败!'); } else { - if (!$db->insert_back_id('sq_agent', array('username' => $_POST['username'], 'password' => $_POST['pass'], 'qq' => $_POST['qq'], 'begintime' => time(), 'levelid' => $_POST['leval'], 'status' => '1', 'superior' => $_SESSION['agent_id']))) { + if (!$db->insert_back_id('sq_agent', array('username' => $_POST['username'], 'password' => wq_hash_password($_POST['pass']), 'qq' => $_POST['qq'], 'begintime' => time(), 'levelid' => $_POST['leval'], 'status' => '1', 'superior' => $_SESSION['agent_id']))) { die('您的余额已扣除但是内部发生错误,下级开通失败,请联系管理员处理!' . $db->geterror()); } else { $db->insert_back_id('sq_log_agent', array('time' => time(), 'aid' => $_SESSION['agent_id'], 'ip' => get_real_ip(), 'msg' => '成功开通下级代理 ' . $_POST['username'])); @@ -876,6 +891,8 @@ switch ($_GET['mod']) { if ($_POST['mod'] != 'username' && $_POST['mod'] != 'password' && $_POST['mod'] != 'qq' && $_POST['mod'] != 'status') die('不支持修改的字段'); if ($_POST['mod'] == 'status') $_POST['value'] = textbooltonum($_POST['value']); + // P0-05: 代理密码以 bcrypt 哈希入库 + if ($_POST['mod'] == 'password') $_POST['value'] = wq_hash_password($_POST['value']); if (!$db->update('sq_agent', array('ID' => $_POST['aid'], 'superior' => $_SESSION['agent_id']), 'AND', array($_POST['mod'] => $_POST['value']))) { die('修改失败' . $db->geterror()); } else { @@ -933,11 +950,12 @@ switch ($_GET['mod']) { if (!$agentinfo = $db->select_first_row('sq_agent', '*', array('username' => $_SESSION['agent_username']), 'AND')) { die('代理信息获取失败'); } - if ($_POST['oldpass'] !== $agentinfo['password']) { + // P0-05: 兼容校验旧明文 / 新 bcrypt;新密码以 bcrypt 入库 + if (!wq_verify_password($_POST['oldpass'], $agentinfo['password'])) { die('输入的原密码错误,无法修改!'); } - if (!$db->update('sq_agent', array('username' => $_SESSION['agent_username']), 'AND', array('password' => $_POST['newpass']))) { + if (!$db->update('sq_agent', array('username' => $_SESSION['agent_username']), 'AND', array('password' => wq_hash_password($_POST['newpass'])))) { die('密码修改失败,服务器内部发生错误'); } else { die('代理密码修改成功,请使用新密码进行登录!'); diff --git a/ajax.php b/ajax.php index c87c0e0..9121a92 100644 --- a/ajax.php +++ b/ajax.php @@ -317,7 +317,8 @@ function dofill() { 'tradeno' => $tradno, 'begintime' => $time, 'user' => $_POST['username'], - 'pass' => $_POST['password'], + // P0-05: 订单密码以 bcrypt 哈希入库(开通落库点 function_auth/trade.inc 有幂等保护) + 'pass' => wq_hash_password($_POST['password']), 'fid' => $_POST['lid'], 'num' => 1, 'paymoney' => $money, @@ -376,7 +377,8 @@ function dofill() { if (!$userinfo = $db->select_first_row('sq_user', '*', array('username' => $_POST['kt_user'], 'appid' => $fidinfo['appid']), 'AND')) { } else { - if ($_POST['kt_pass'] !== $userinfo['password']) { + // P0-05: 兼容旧明文 / 新 bcrypt 校验续费用户密码 + if (!wq_verify_password($_POST['kt_pass'], $userinfo['password'])) { die(json_encode(array('code' => -2, 'msg' => '您的用户名已开通,您需要输入的正确密码才能进行续费,当前输入的用户密码错误!'))); } } @@ -385,7 +387,7 @@ function dofill() { 'tradeno' => $tradno, 'begintime' => $time, 'user' => $_POST['kt_user'], - 'pass' => $_POST['kt_pass'], + 'pass' => wq_hash_password($_POST['kt_pass']), 'fid' => $_POST['id'], 'num' => $_POST['kt_num'], 'paymoney' => $spendmoney, @@ -770,7 +772,8 @@ function buy_submit(id,type) { if (!$userinfo = $db->select_first_row('sq_user', '*', array('username' => $_POST['kt_user'], 'appid' => $fidinfo['appid']), 'AND')) { } else { - if ($_POST['kt_pass'] !== $userinfo['password']) { + // P0-05: 兼容旧明文 / 新 bcrypt 校验 + if (!wq_verify_password($_POST['kt_pass'], $userinfo['password'])) { die(json_encode(array('code' => -2, 'msg' => '用户密码错误!'))); } } @@ -778,7 +781,7 @@ function buy_submit(id,type) { $newtrade = array('name' => $fidinfo['fidname'], 'begintime' => $time, 'user' => $_POST['kt_user'], - 'pass' => $_POST['kt_pass'], + 'pass' => wq_hash_password($_POST['kt_pass']), 'fid' => $_POST['id'], 'mail' => $_POST['kt_mail'], 'kami' => $_POST['kt_key'], @@ -999,9 +1002,15 @@ function buy_submit(id,type) { if (empty($_POST['kt_user']) || empty($_POST['kt_pass'])){ die(makejson(-2,'请输入您的登录信息')); } - if (!$userinfo = $db->select_first_row('sq_user','ID,sendtime,mail',array('username'=>$_POST['kt_user'],'password'=>$_POST['kt_pass'],'appid'=>$appid),'AND')){ + // P0-05: 先按用户名+应用取出,再在 PHP 中校验密码(兼容旧明文 / 新 bcrypt), + // 校验成功且为旧明文时惰性升级为 bcrypt + if (!$userinfo = $db->select_first_row('sq_user','ID,sendtime,mail,password',array('username'=>$_POST['kt_user'],'appid'=>$appid),'AND') + || !wq_verify_password($_POST['kt_pass'], $userinfo['password'])){ die(makejson(-3,'未查询到您的授权信息!
请检查您输入的账号密码是否正确!')); } + if (!wq_is_hashed_password($userinfo['password'])){ + $db->update('sq_user',array('ID'=>$userinfo['ID']),'AND',array('password'=>wq_hash_password($_POST['kt_pass']))); + } }else if ($appinfo['logintype'] === 'kmsq'){ if (empty($_POST['kt_user'])){ die(makejson(-2,'请输入您登录使用的卡密')); diff --git a/api.php b/api.php index eb90e72..6ab1433 100644 --- a/api.php +++ b/api.php @@ -132,9 +132,13 @@ switch ($_GET['mod']){ if(!$userinfo = $db->select_first_row('sq_user','*',array('appid'=>$_GET['appid'],'username'=>$postdata['user']),'AND')){ backmsg('-1','账号不存在'); } - if ($postdata['pass'] !== $userinfo['password']){ + // P0-05: 兼容新 bcrypt / 旧明文校验;旧明文校验成功后惰性升级为 bcrypt + if (!wq_verify_password($postdata['pass'], $userinfo['password'])){ backmsg('-2','您输入的密码错误'); } + if (!wq_is_hashed_password($userinfo['password'])){ + $db->update('sq_user',array('ID'=>$userinfo['ID']),'AND',array('password'=>wq_hash_password($postdata['pass']))); + } }else if ($appinfo['logintype'] == 'kmsq'){ if(!$userinfo = $db->select_first_row('sq_user','*',array('appid'=>$_GET['appid'],'username'=>$postdata['user']),'AND')){ backmsg('-1','授权卡密不存在'); @@ -276,7 +280,8 @@ switch ($_GET['mod']){ backmsg('-13','验证码已过期,请尝试重新获取'); } - $db->update('sq_user',array('ID'=>$userinfo['ID']),'AND',array('password'=>$postdata['newpass'])); + // P0-05: 新密码以 bcrypt 哈希入库 + $db->update('sq_user',array('ID'=>$userinfo['ID']),'AND',array('password'=>wq_hash_password($postdata['newpass']))); backmsg('1'); break; case 'SubscriberDownline': @@ -337,8 +342,11 @@ switch ($_GET['mod']){ if (time()-$userinfo['sendtime'] < 60){ backmsg('-1','邮件发送过于频繁,请耐心等待'.(time()-$userinfo['sendtime']).'秒后发送'); } - $db->update('sq_user',array('ID'=>$userinfo['ID']),'AND',array('sendtime'=>time())); - sendemail('找回密码 - '.$appinfo['appname'],'['.$userinfo['username'].']您的密码为:'.$userinfo['password'],$userinfo['mail']); + // P0-05: 密码已以 bcrypt 哈希入库,原明文不再可取出,也禁止邮件外发。 + // 改为"重置为一次性随机新密码,仅通过用户本人邮箱投递一次" + $newpass = bin2hex(random_bytes(6)); + $db->update('sq_user',array('ID'=>$userinfo['ID']),'AND',array('password'=>wq_hash_password($newpass),'sendtime'=>time())); + sendemail('密码重置 - '.$appinfo['appname'],'['.$userinfo['username'].']您的密码已重置,新密码为:'.$newpass.',请立即登录并尽快修改密码。',$userinfo['mail']); backmsg('1'); break; @@ -361,9 +369,13 @@ function getuserinfo($appinfo,$postdata){ if(!$userinfo = $db->select_first_row('sq_user','*',array('appid'=>$_GET['appid'],'username'=>$postdata['user']),'AND')){ backmsg('-1','账号不存在'); } - if ($postdata['pass'] !== $userinfo['password']){ + // P0-05: 兼容新 bcrypt / 旧明文校验;旧明文校验成功后惰性升级为 bcrypt + if (!wq_verify_password($postdata['pass'], $userinfo['password'])){ backmsg('-2','您输入的密码错误'); } + if (!wq_is_hashed_password($userinfo['password'])){ + $db->update('sq_user',array('ID'=>$userinfo['ID']),'AND',array('password'=>wq_hash_password($postdata['pass']))); + } }else if ($appinfo['logintype'] == 'kmsq'){ if(!$userinfo = $db->select_first_row('sq_user','*',array('appid'=>$_GET['appid'],'username'=>$postdata['user']),'AND')){ backmsg('-1','授权卡密不存在'); diff --git a/api/Communication.php b/api/Communication.php index 66e72a2..296092c 100644 --- a/api/Communication.php +++ b/api/Communication.php @@ -50,7 +50,11 @@ if ($data['mod'] === 'Login'){ if (!$userinfo = $db->select_first_row('sq_user', '*', array('appid' => $_GET['appid'], 'username' => $data['user']), 'AND')) $communication->back(-204,'ErrorUsername'); - if ($data['pass'] !== $userinfo['password']) $communication->back(-205,'ErrorPassword'); + // P0-05: 兼容旧明文 / 新 bcrypt 校验用户密码;旧明文校验成功后惰性升级为 bcrypt + if (!wq_verify_password($data['pass'], $userinfo['password'])) $communication->back(-205,'ErrorPassword'); + if (!wq_is_hashed_password($userinfo['password'])) { + $db->update('sq_user', array('ID' => $userinfo['ID']), 'AND', array('password' => wq_hash_password($data['pass']))); + } } else if ($appinfo['logintype'] == 'kmsq') { if (empty($data['user'])) $communication->back(-211,'NoKami'); diff --git a/function/communication.php b/function/communication.php index 46cfbd1..039be87 100644 --- a/function/communication.php +++ b/function/communication.php @@ -51,7 +51,11 @@ if ($data['mod'] === 'Login'){ if (!$userinfo = $db->select_first_row('sq_user', '*', array('appid' => $_GET['appid'], 'username' => $data['user']), 'AND')) $communication->back(-204,'ErrorUsername'); - if ($data['pass'] !== $userinfo['password']) $communication->back(-205,'ErrorPassword'); + // P0-05: 兼容旧明文 / 新 bcrypt 校验用户密码;旧明文校验成功后惰性升级为 bcrypt + if (!wq_verify_password($data['pass'], $userinfo['password'])) $communication->back(-205,'ErrorPassword'); + if (!wq_is_hashed_password($userinfo['password'])) { + $db->update('sq_user', array('ID' => $userinfo['ID']), 'AND', array('password' => wq_hash_password($data['pass']))); + } } else if ($appinfo['logintype'] == 'kmsq') { if (empty($data['user'])) $communication->back(-211,'NoKami'); diff --git a/function/function_auth.php b/function/function_auth.php index 83549ad..2dbade2 100644 --- a/function/function_auth.php +++ b/function/function_auth.php @@ -23,9 +23,16 @@ * @return int 1为新开成功,2为续费成功,3为卡密新开成功 */ function auth_add($username,$password,$ip,$balance,$uqq,$mail,$appid,$origin,$oid,$aid,&$newkey,&$tips,$tradeinfo = array()){ + include_once __DIR__ . '/function_core.php'; include_once __DIR__ . '/function_app.php'; global $db,$G,$MailTips; + // P0-05: 密码以 bcrypt 哈希入库。幂等保护:若上游(订单创建点)已哈希则原样保留, + // 旧格式明文订单(升级前产生)在此处补哈希 + if (!wq_is_hashed_password($password)) { + $password = wq_hash_password($password); + } + $appinfo = app_idgetinfo($appid); if ($appinfo['usetype']=='dqsj'){ diff --git a/function/function_core.php b/function/function_core.php index bd41838..550adf9 100644 --- a/function/function_core.php +++ b/function/function_core.php @@ -211,6 +211,46 @@ function updateset($name, $value) $G['config'][$name] = $value; } +/* ---------- P0-05:密码哈希(bcrypt)与旧格式兼容 ---------- */ + +/** + * 判断存储的密码值是否为新 bcrypt 哈希 + */ +function wq_is_hashed_password($stored) +{ + return is_string($stored) && strlen($stored) === 60 && strpos($stored, '$2y$') === 0; +} + +/** + * 生成新密码的入库值(bcrypt) + */ +function wq_hash_password($plain) +{ + return password_hash((string)$plain, PASSWORD_BCRYPT); +} + +/** + * 校验密码(兼容旧格式): + * - 存储值为 bcrypt -> password_verify + * - 旧 sq_admin(md5 存储)-> $legacy='md5',与 md5(明文) 比对 + * - 旧 sq_user/sq_agent(明文存储)-> 直接比对 + * @param string $plain 明文密码 + * @param string $stored 数据库存储值 + * @param string $legacy 'plain'(用户/代理旧格式)或 'md5'(管理员旧格式) + */ +function wq_verify_password($plain, $stored, $legacy = 'plain') +{ + $plain = (string)$plain; + $stored = (string)$stored; + if (wq_is_hashed_password($stored)) { + return password_verify($plain, $stored); + } + if ($legacy === 'md5') { + return hash_equals($stored, md5($plain)); + } + return hash_equals($stored, $plain); +} + /* * 布尔逻辑型转换为数字0或1 diff --git a/function/trade.inc.php b/function/trade.inc.php index a78c632..2cca7df 100644 --- a/function/trade.inc.php +++ b/function/trade.inc.php @@ -81,6 +81,11 @@ function trade_do($tradeinfo){ } if ($tradeinfo['type'] == '4') { $nowtime = Get_Date(); + // P0-05: 代理密码以 bcrypt 哈希入库。幂等保护:订单创建点已哈希则原样保留, + // 旧格式明文订单(升级前产生)在此处补哈希 + if (!wq_is_hashed_password($tradeinfo['pass'])) { + $tradeinfo['pass'] = wq_hash_password($tradeinfo['pass']); + } $db->insert_back_id('sq_agent', array('username' => $tradeinfo['user'], 'password' => $tradeinfo['pass'], 'begintime' => time(), 'levelid' => $tradeinfo['fid'], 'status' => 1, 'qq' => $tradeinfo['uqq'])); $T['title'] = '您的代理已成功开通!'; $T['content'][] = 'QQ:'.$tradeinfo['uqq']; diff --git a/wenquan_auth.sql b/wenquan_auth.sql index 6476abf..217a99f 100644 --- a/wenquan_auth.sql +++ b/wenquan_auth.sql @@ -31,7 +31,7 @@ SET time_zone = "+00:00"; CREATE TABLE `sq_admin` ( `ID` int(11) NOT NULL, `username` varchar(255) NOT NULL, - `password` varchar(33) NOT NULL, + `password` varchar(255) NOT NULL, `loginip` varchar(20) NOT NULL, `logintime` int(11) NOT NULL, `qq` varchar(12) NOT NULL,