加固-06(P0-05): 密码全部以 bcrypt 哈希入库,旧格式(明文/MD5)兼容并惰性迁移
背景:sq_user/sq_agent 密码明文入库、sq_admin 存 MD5;订单表 sq_trade.pass 明文在途;
找回密码 API 会把明文密码直接发邮件;日志记录明文密码。数据库泄露 = 全部账号密码泄露。
1. function/function_core.php 新增 3 个 helper(updateset 之后):
- wq_is_hashed_password($v):判断存储值是否为新 bcrypt 哈希(60 长度 $2y$ 前缀)
- wq_hash_password($plain):password_hash(PASSWORD_BCRYPT)
- wq_verify_password($plain,$stored,$legacy):兼容 新 bcrypt / 旧明文(sq_user/sq_agent) / 旧 md5(sq_admin),
哈希比对一律 hash_equals,恒定时间比较防时序侧信道
2. 所有落库点改为 bcrypt:
- 用户开户漏斗 function/function_auth.php auth_add 入口幂等补哈希(上游已哈希则原样保留)
- 代理开通漏斗 function/trade.inc.php type=4 代理落库前幂等补哈希
- 下单点订单密码哈希入库:ajax.php(320/388/781)、agent/ajax.php(439) —— 订单表不再有明文在途密码
- admin/ajax.php:addagent、addadmin、changeagent(mod=password)、changepassword 新密码
- agent/ajax.php:开下级代理、changeuser(mod=password)、changeagent(mod=password)、changepassword 新密码
- api.php:ChangePassword 写库
- api/Communication.php 与 function/communication.php:用户登录校验成功后,旧明文惰性升级为 bcrypt
3. 所有校验点改为取行 + PHP 校验(不再 WHERE password=明文):
- admin 登录(旧 MD5 兼容,成功即写回 bcrypt,session 与 DB 存同一新哈希保住 re-check 机制)
- agent 密码登录(旧明文兼容,惰性迁移);agent token 登录 session 改存 DB 存储值
- 根 ajax.php 续费 kt 密码校验(379/773)、卡密找回密码(1002)
- api.php GetUserInfo 内联校验、getuserinfo() 校验(均带惰性迁移)
4. 找回密码改造(api.php RetrievePassword):
密码已不可逆,原"邮件下发原密码"改为"重置为一次性随机新密码(bin2hex(random_bytes(6)))+ 哈希落库 + 仅邮件投递一次"
5. 日志/回传去明文:
- admin 登录失败日志不再记录明文密码(改记账号)
- admin getagentinfo 不再回传密码值(掩码 ********,经确认 UI 无回写风险)
6. 表结构:sq_admin.password varchar(33) -> varchar(255)(bcrypt 60 字符装不下)
- wenquan_auth.sql 同步更新(新装库直接可用)
- 已有库需执行:ALTER TABLE sq_admin MODIFY password varchar(255) NOT NULL;(本次本地库已执行)
回归(40 项全 PASS,8082 内置服务器 + 8081 nginx 双通道冒烟):
- API(c=api) 旧明文用户登录成功即升级 bcrypt;再登录幂等不错哈希;错密码 -205 被拒
- admin 旧 MD5 登录即迁移 bcrypt;再登录/错密码/日志无明文/checklogin 会话重校验均通过
- admin 新增管理员、改密(旧密码失效/新密码生效/恢复基线)
- admin 新增代理直接 bcrypt;getagentinfo 掩码;changeagent 改密哈希入库
- 旧明文代理登录即迁移 bcrypt;checklogin 通过;代理改密旧失效新生效
- admin 手工开通(funnel)明文 POST 直接存 bcrypt;API 登录新开通用户成功
- 注:测试应用 free 必须为 0(free=1 时 Login 入口直接放行,属产品设计,不走密码校验)
已知行为变化(记录):用户/代理列表按"密码"关键词搜索不再命中(存储已哈希,搜索本身即泄露向量,收紧);
列表中密码列显示 60 位哈希串而非明文;改密会使该账号现有会话失效需重新登录(与旧行为一致)。
api.php 为 2024 树中的旧入口(已被 api/Communication.php 取代),仍按同口径同步修了 4 处密码点防复活踩坑。
This commit is contained in:
+22
-10
@@ -34,17 +34,20 @@ if ($_GET['mod'] === 'login'){
|
|||||||
if ($verification !== true) {
|
if ($verification !== true) {
|
||||||
die(json_encode(array('code' => '-88', 'msg' => '请先进行人机验证')));
|
die(json_encode(array('code' => '-88', 'msg' => '请先进行人机验证')));
|
||||||
}
|
}
|
||||||
if (!$result = $db->select_first_row('sq_admin','*',array('username'=>$_POST['username'],'password'=>md5($_POST['password'])),'AND')){
|
// P0-05: 按用户名取出后用 PHP 校验(兼容新 bcrypt / 旧 md5),成功即写回 bcrypt(惰性迁移);
|
||||||
//$db->insert_back_id('sq_log_system',array('time'=>time(),'ip'=>get_real_ip(),'msg'=>'管理员 '.$_POST['username'].'使用密码'.$_POST['password'].'登陆失败:密码错误或账号不存在','type'=>'danger'));
|
// 失败日志不再记录明文密码(原 posterror 会把密码写入 sq_log_system)
|
||||||
$db->posterror('管理员登录尝试失败,账号['.$_POST['username'].']密码['.$_POST['password'].']','success');
|
$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())));
|
die(json_encode(array('code' => -3, 'msg' => '输入的账号密码错误!'.$db->geterror())));
|
||||||
}else{
|
}else{
|
||||||
$_SESSION['admin_username'] = $_POST['username'];
|
$_SESSION['admin_username'] = $_POST['username'];
|
||||||
$_SESSION['admin_id'] = $result['ID'];
|
$_SESSION['admin_id'] = $result['ID'];
|
||||||
$_SESSION['admin_qq'] = $result['qq'];
|
$_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'];
|
$_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->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');
|
$db->posterror('管理员 '.$_POST['username'].'使用密码登录后台成功','success');
|
||||||
die(json_encode(array('code' => '1', 'msg' => '登陆成功,正在跳转!')));
|
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']))){
|
if (!$db->update('sq_user',array('ID'=>$_POST['userid']),'AND',array($_POST['mod']=>$_POST['value']))){
|
||||||
die('修改失败'.$db->geterror());
|
die('修改失败'.$db->geterror());
|
||||||
}else{
|
}else{
|
||||||
@@ -624,7 +632,7 @@ switch ($_GET['mod']){
|
|||||||
if ($db->select_first_row('sq_agent','*',array('username'=>$_POST['agent_name']),'AND') != false){
|
if ($db->select_first_row('sq_agent','*',array('username'=>$_POST['agent_name']),'AND') != false){
|
||||||
die('该代理账号已经存在,请尝试其他用户名');
|
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());
|
die('添加失败:'.$db->geterror());
|
||||||
}else{
|
}else{
|
||||||
die('代理添加成功!');
|
die('代理添加成功!');
|
||||||
@@ -674,11 +682,12 @@ switch ($_GET['mod']){
|
|||||||
break;
|
break;
|
||||||
case 'getagentinfo':
|
case 'getagentinfo':
|
||||||
$result = $db->select_first_row('sq_agent','*',array('ID'=>$_POST['id']),'AND');
|
$result = $db->select_first_row('sq_agent','*',array('ID'=>$_POST['id']),'AND');
|
||||||
|
// P0-05: 不再把密码(哈希或明文)回传前端;密码修改走 changeagent 单独入口
|
||||||
die(json_encode(array(
|
die(json_encode(array(
|
||||||
'agent_leval'=>$result['levelid'],
|
'agent_leval'=>$result['levelid'],
|
||||||
'agent_money'=>$result['money'],
|
'agent_money'=>$result['money'],
|
||||||
'agent_name'=>$result['username'],
|
'agent_name'=>$result['username'],
|
||||||
'agent_pass'=>$result['password']
|
'agent_pass'=>'********'
|
||||||
|
|
||||||
)));
|
)));
|
||||||
break;
|
break;
|
||||||
@@ -695,6 +704,8 @@ switch ($_GET['mod']){
|
|||||||
die('代理ID不能为空');
|
die('代理ID不能为空');
|
||||||
}
|
}
|
||||||
if ($_POST['mod'] == 'status') $_POST['value'] = textbooltonum($_POST['value']);
|
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']))){
|
if (!$db->update('sq_agent',array('ID'=>$_POST['aid']),'AND',array($_POST['mod']=>$_POST['value']))){
|
||||||
die('修改失败'.$db->geterror());
|
die('修改失败'.$db->geterror());
|
||||||
}else{
|
}else{
|
||||||
@@ -762,7 +773,7 @@ switch ($_GET['mod']){
|
|||||||
if (empty($_POST['addusername']) || empty($_POST['adduserpass']) || empty($_POST['adduserqq'])){
|
if (empty($_POST['addusername']) || empty($_POST['adduserpass']) || empty($_POST['adduserqq'])){
|
||||||
die('数据不能为空,请检查');
|
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进行删除');
|
die('管理员新增成功,如果需要删除请进数据库中的表sq_admin进行删除');
|
||||||
break;
|
break;
|
||||||
case 'sendtestmail':
|
case 'sendtestmail':
|
||||||
@@ -1050,11 +1061,12 @@ switch ($_GET['mod']){
|
|||||||
if (!$agentinfo = $db->select_first_row('sq_admin','*',array('username'=>$_SESSION['admin_username']),'AND')){
|
if (!$agentinfo = $db->select_first_row('sq_admin','*',array('username'=>$_SESSION['admin_username']),'AND')){
|
||||||
die('管理员信息获取失败');
|
die('管理员信息获取失败');
|
||||||
}
|
}
|
||||||
if (md5($_POST['oldpass']) !== $agentinfo['password']){
|
// P0-05: 兼容校验旧 md5 / 新 bcrypt;新密码以 bcrypt 入库
|
||||||
|
if (!wq_verify_password($_POST['oldpass'], $agentinfo['password'], 'md5')){
|
||||||
die('输入的原密码错误,无法修改!');
|
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('密码修改失败,服务器内部发生错误');
|
die('密码修改失败,服务器内部发生错误');
|
||||||
}else{
|
}else{
|
||||||
die('管理密码修改成功,请使用新密码进行登录!');
|
die('管理密码修改成功,请使用新密码进行登录!');
|
||||||
|
|||||||
+27
-9
@@ -12,8 +12,9 @@ if ($_GET['mod'] === 'login') {
|
|||||||
if (!$result = $db->select_first_row('sq_agent', '*', array('accesstoken' => $_POST['token']), 'AND')) {
|
if (!$result = $db->select_first_row('sq_agent', '*', array('accesstoken' => $_POST['token']), 'AND')) {
|
||||||
die(json_encode(array('code' => '-1', 'msg' => '秘钥错误')));
|
die(json_encode(array('code' => '-1', 'msg' => '秘钥错误')));
|
||||||
} else {
|
} else {
|
||||||
$_SESSION['agent_username'] = $_POST['username'];
|
$_SESSION['agent_username'] = $result['username'];
|
||||||
$_SESSION['agent_password'] = $_POST['password'];
|
// P0-05: 会话持有数据库中的"存储值"(新 bcrypt / 旧明文),与重校验 WHERE password=会话 保持一致
|
||||||
|
$_SESSION['agent_password'] = $result['password'];
|
||||||
$_SESSION['agent_id'] = $result['ID'];
|
$_SESSION['agent_id'] = $result['ID'];
|
||||||
$_SESSION['agent_qq'] = $result['qq'];
|
$_SESSION['agent_qq'] = $result['qq'];
|
||||||
$_SESSION['agent_HTTP_USER_AGENT'] = $_SERVER['HTTP_USER_AGENT'];
|
$_SESSION['agent_HTTP_USER_AGENT'] = $_SERVER['HTTP_USER_AGENT'];
|
||||||
@@ -35,18 +36,22 @@ if ($_GET['mod'] === 'login') {
|
|||||||
die(json_encode(array('code' => -2, 'msg' => '请输入您的密码')));
|
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())));
|
die(json_encode(array('code' => -3, 'msg' => '输入的账号密码错误!' . $db->geterror())));
|
||||||
} else {
|
} else {
|
||||||
if ($result['status'] != '1') {
|
if ($result['status'] != '1') {
|
||||||
die(json_encode(array('code' => -4, 'msg' => '代理账号已被冻结,请联系管理员或者上级处理')));
|
die(json_encode(array('code' => -4, 'msg' => '代理账号已被冻结,请联系管理员或者上级处理')));
|
||||||
}
|
}
|
||||||
|
$newhash = wq_hash_password($_POST['password']);
|
||||||
$_SESSION['agent_username'] = $_POST['username'];
|
$_SESSION['agent_username'] = $_POST['username'];
|
||||||
$_SESSION['agent_password'] = $_POST['password'];
|
$_SESSION['agent_password'] = $newhash;
|
||||||
$_SESSION['agent_id'] = $result['ID'];
|
$_SESSION['agent_id'] = $result['ID'];
|
||||||
$_SESSION['agent_qq'] = $result['qq'];
|
$_SESSION['agent_qq'] = $result['qq'];
|
||||||
$_SESSION['agent_HTTP_USER_AGENT'] = $_SERVER['HTTP_USER_AGENT'];
|
$_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' => '登陆成功,正在跳转!')));
|
die(json_encode(array('code' => '1', 'msg' => '登陆成功,正在跳转!')));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,6 +301,10 @@ switch ($_GET['mod']) {
|
|||||||
if ($_POST['mod'] == 'status') {
|
if ($_POST['mod'] == 'status') {
|
||||||
$_POST['value'] = textbooltonum($_POST['value']);
|
$_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['mod'] == 'balance') {
|
||||||
if ($_POST['value'] == '永久使用') {
|
if ($_POST['value'] == '永久使用') {
|
||||||
$_POST['value'] = -1;
|
$_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']))) {
|
if (!$db->update('sq_user', array('ID' => $_POST['userid'], 'aid' => $_SESSION['agent_id']), 'AND', array($_POST['mod'] => $_POST['value']))) {
|
||||||
die('修改失败' . $db->geterror());
|
die('修改失败' . $db->geterror());
|
||||||
} else {
|
} else {
|
||||||
@@ -436,7 +450,8 @@ switch ($_GET['mod']) {
|
|||||||
'tradeno' => $tradno,
|
'tradeno' => $tradno,
|
||||||
'begintime' => $time,
|
'begintime' => $time,
|
||||||
'user' => $_POST['kt_user'],
|
'user' => $_POST['kt_user'],
|
||||||
'pass' => $_POST['kt_pass'],
|
// P0-05: 订单中的密码直接以 bcrypt 哈希存库(开通落库点 function_auth 有幂等保护,不会二次哈希)
|
||||||
|
'pass' => wq_hash_password($_POST['kt_pass']),
|
||||||
'fid' => $_POST['id'],
|
'fid' => $_POST['id'],
|
||||||
'num' => $_POST['kt_num'],
|
'num' => $_POST['kt_num'],
|
||||||
'paymoney' => $spendmoney,
|
'paymoney' => $spendmoney,
|
||||||
@@ -819,7 +834,7 @@ switch ($_GET['mod']) {
|
|||||||
if (!$db->update('sq_agent', array('username' => $_SESSION['agent_username']), 'AND', array('money' => $newmoney))) {
|
if (!$db->update('sq_agent', array('username' => $_SESSION['agent_username']), 'AND', array('money' => $newmoney))) {
|
||||||
die('系统内部错误,开通失败!');
|
die('系统内部错误,开通失败!');
|
||||||
} else {
|
} 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());
|
die('您的余额已扣除但是内部发生错误,下级开通失败,请联系管理员处理!' . $db->geterror());
|
||||||
} else {
|
} else {
|
||||||
$db->insert_back_id('sq_log_agent', array('time' => time(), 'aid' => $_SESSION['agent_id'], 'ip' => get_real_ip(), 'msg' => '成功开通下级代理 ' . $_POST['username']));
|
$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'] != 'username' && $_POST['mod'] != 'password' && $_POST['mod'] != 'qq' && $_POST['mod'] != 'status') die('不支持修改的字段');
|
||||||
|
|
||||||
if ($_POST['mod'] == 'status') $_POST['value'] = textbooltonum($_POST['value']);
|
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']))) {
|
if (!$db->update('sq_agent', array('ID' => $_POST['aid'], 'superior' => $_SESSION['agent_id']), 'AND', array($_POST['mod'] => $_POST['value']))) {
|
||||||
die('修改失败' . $db->geterror());
|
die('修改失败' . $db->geterror());
|
||||||
} else {
|
} else {
|
||||||
@@ -933,11 +950,12 @@ switch ($_GET['mod']) {
|
|||||||
if (!$agentinfo = $db->select_first_row('sq_agent', '*', array('username' => $_SESSION['agent_username']), 'AND')) {
|
if (!$agentinfo = $db->select_first_row('sq_agent', '*', array('username' => $_SESSION['agent_username']), 'AND')) {
|
||||||
die('代理信息获取失败');
|
die('代理信息获取失败');
|
||||||
}
|
}
|
||||||
if ($_POST['oldpass'] !== $agentinfo['password']) {
|
// P0-05: 兼容校验旧明文 / 新 bcrypt;新密码以 bcrypt 入库
|
||||||
|
if (!wq_verify_password($_POST['oldpass'], $agentinfo['password'])) {
|
||||||
die('输入的原密码错误,无法修改!');
|
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('密码修改失败,服务器内部发生错误');
|
die('密码修改失败,服务器内部发生错误');
|
||||||
} else {
|
} else {
|
||||||
die('代理密码修改成功,请使用新密码进行登录!');
|
die('代理密码修改成功,请使用新密码进行登录!');
|
||||||
|
|||||||
@@ -317,7 +317,8 @@ function dofill() {
|
|||||||
'tradeno' => $tradno,
|
'tradeno' => $tradno,
|
||||||
'begintime' => $time,
|
'begintime' => $time,
|
||||||
'user' => $_POST['username'],
|
'user' => $_POST['username'],
|
||||||
'pass' => $_POST['password'],
|
// P0-05: 订单密码以 bcrypt 哈希入库(开通落库点 function_auth/trade.inc 有幂等保护)
|
||||||
|
'pass' => wq_hash_password($_POST['password']),
|
||||||
'fid' => $_POST['lid'],
|
'fid' => $_POST['lid'],
|
||||||
'num' => 1,
|
'num' => 1,
|
||||||
'paymoney' => $money,
|
'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')) {
|
if (!$userinfo = $db->select_first_row('sq_user', '*', array('username' => $_POST['kt_user'], 'appid' => $fidinfo['appid']), 'AND')) {
|
||||||
|
|
||||||
} else {
|
} 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' => '您的用户名已开通,您需要输入的正确密码才能进行续费,当前输入的用户密码错误!')));
|
die(json_encode(array('code' => -2, 'msg' => '您的用户名已开通,您需要输入的正确密码才能进行续费,当前输入的用户密码错误!')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -385,7 +387,7 @@ function dofill() {
|
|||||||
'tradeno' => $tradno,
|
'tradeno' => $tradno,
|
||||||
'begintime' => $time,
|
'begintime' => $time,
|
||||||
'user' => $_POST['kt_user'],
|
'user' => $_POST['kt_user'],
|
||||||
'pass' => $_POST['kt_pass'],
|
'pass' => wq_hash_password($_POST['kt_pass']),
|
||||||
'fid' => $_POST['id'],
|
'fid' => $_POST['id'],
|
||||||
'num' => $_POST['kt_num'],
|
'num' => $_POST['kt_num'],
|
||||||
'paymoney' => $spendmoney,
|
'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')) {
|
if (!$userinfo = $db->select_first_row('sq_user', '*', array('username' => $_POST['kt_user'], 'appid' => $fidinfo['appid']), 'AND')) {
|
||||||
|
|
||||||
} else {
|
} 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' => '用户密码错误!')));
|
die(json_encode(array('code' => -2, 'msg' => '用户密码错误!')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -778,7 +781,7 @@ function buy_submit(id,type) {
|
|||||||
$newtrade = array('name' => $fidinfo['fidname'],
|
$newtrade = array('name' => $fidinfo['fidname'],
|
||||||
'begintime' => $time,
|
'begintime' => $time,
|
||||||
'user' => $_POST['kt_user'],
|
'user' => $_POST['kt_user'],
|
||||||
'pass' => $_POST['kt_pass'],
|
'pass' => wq_hash_password($_POST['kt_pass']),
|
||||||
'fid' => $_POST['id'],
|
'fid' => $_POST['id'],
|
||||||
'mail' => $_POST['kt_mail'],
|
'mail' => $_POST['kt_mail'],
|
||||||
'kami' => $_POST['kt_key'],
|
'kami' => $_POST['kt_key'],
|
||||||
@@ -999,9 +1002,15 @@ function buy_submit(id,type) {
|
|||||||
if (empty($_POST['kt_user']) || empty($_POST['kt_pass'])){
|
if (empty($_POST['kt_user']) || empty($_POST['kt_pass'])){
|
||||||
die(makejson(-2,'请输入您的登录信息'));
|
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,'未查询到您的授权信息!<br>请检查您输入的账号密码是否正确!'));
|
die(makejson(-3,'未查询到您的授权信息!<br>请检查您输入的账号密码是否正确!'));
|
||||||
}
|
}
|
||||||
|
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'){
|
}else if ($appinfo['logintype'] === 'kmsq'){
|
||||||
if (empty($_POST['kt_user'])){
|
if (empty($_POST['kt_user'])){
|
||||||
die(makejson(-2,'请输入您登录使用的卡密'));
|
die(makejson(-2,'请输入您登录使用的卡密'));
|
||||||
|
|||||||
@@ -132,9 +132,13 @@ switch ($_GET['mod']){
|
|||||||
if(!$userinfo = $db->select_first_row('sq_user','*',array('appid'=>$_GET['appid'],'username'=>$postdata['user']),'AND')){
|
if(!$userinfo = $db->select_first_row('sq_user','*',array('appid'=>$_GET['appid'],'username'=>$postdata['user']),'AND')){
|
||||||
backmsg('-1','账号不存在');
|
backmsg('-1','账号不存在');
|
||||||
}
|
}
|
||||||
if ($postdata['pass'] !== $userinfo['password']){
|
// P0-05: 兼容新 bcrypt / 旧明文校验;旧明文校验成功后惰性升级为 bcrypt
|
||||||
|
if (!wq_verify_password($postdata['pass'], $userinfo['password'])){
|
||||||
backmsg('-2','您输入的密码错误');
|
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'){
|
}else if ($appinfo['logintype'] == 'kmsq'){
|
||||||
if(!$userinfo = $db->select_first_row('sq_user','*',array('appid'=>$_GET['appid'],'username'=>$postdata['user']),'AND')){
|
if(!$userinfo = $db->select_first_row('sq_user','*',array('appid'=>$_GET['appid'],'username'=>$postdata['user']),'AND')){
|
||||||
backmsg('-1','授权卡密不存在');
|
backmsg('-1','授权卡密不存在');
|
||||||
@@ -276,7 +280,8 @@ switch ($_GET['mod']){
|
|||||||
backmsg('-13','验证码已过期,请尝试重新获取');
|
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');
|
backmsg('1');
|
||||||
break;
|
break;
|
||||||
case 'SubscriberDownline':
|
case 'SubscriberDownline':
|
||||||
@@ -337,8 +342,11 @@ switch ($_GET['mod']){
|
|||||||
if (time()-$userinfo['sendtime'] < 60){
|
if (time()-$userinfo['sendtime'] < 60){
|
||||||
backmsg('-1','邮件发送过于频繁,请耐心等待'.(time()-$userinfo['sendtime']).'秒后发送');
|
backmsg('-1','邮件发送过于频繁,请耐心等待'.(time()-$userinfo['sendtime']).'秒后发送');
|
||||||
}
|
}
|
||||||
$db->update('sq_user',array('ID'=>$userinfo['ID']),'AND',array('sendtime'=>time()));
|
// P0-05: 密码已以 bcrypt 哈希入库,原明文不再可取出,也禁止邮件外发。
|
||||||
sendemail('找回密码 - '.$appinfo['appname'],'['.$userinfo['username'].']您的密码为:'.$userinfo['password'],$userinfo['mail']);
|
// 改为"重置为一次性随机新密码,仅通过用户本人邮箱投递一次"
|
||||||
|
$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');
|
backmsg('1');
|
||||||
break;
|
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')){
|
if(!$userinfo = $db->select_first_row('sq_user','*',array('appid'=>$_GET['appid'],'username'=>$postdata['user']),'AND')){
|
||||||
backmsg('-1','账号不存在');
|
backmsg('-1','账号不存在');
|
||||||
}
|
}
|
||||||
if ($postdata['pass'] !== $userinfo['password']){
|
// P0-05: 兼容新 bcrypt / 旧明文校验;旧明文校验成功后惰性升级为 bcrypt
|
||||||
|
if (!wq_verify_password($postdata['pass'], $userinfo['password'])){
|
||||||
backmsg('-2','您输入的密码错误');
|
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'){
|
}else if ($appinfo['logintype'] == 'kmsq'){
|
||||||
if(!$userinfo = $db->select_first_row('sq_user','*',array('appid'=>$_GET['appid'],'username'=>$postdata['user']),'AND')){
|
if(!$userinfo = $db->select_first_row('sq_user','*',array('appid'=>$_GET['appid'],'username'=>$postdata['user']),'AND')){
|
||||||
backmsg('-1','授权卡密不存在');
|
backmsg('-1','授权卡密不存在');
|
||||||
|
|||||||
@@ -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 (!$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') {
|
} else if ($appinfo['logintype'] == 'kmsq') {
|
||||||
if (empty($data['user'])) $communication->back(-211,'NoKami');
|
if (empty($data['user'])) $communication->back(-211,'NoKami');
|
||||||
|
|||||||
@@ -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 (!$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') {
|
} else if ($appinfo['logintype'] == 'kmsq') {
|
||||||
if (empty($data['user'])) $communication->back(-211,'NoKami');
|
if (empty($data['user'])) $communication->back(-211,'NoKami');
|
||||||
|
|||||||
@@ -23,9 +23,16 @@
|
|||||||
* @return int 1为新开成功,2为续费成功,3为卡密新开成功
|
* @return int 1为新开成功,2为续费成功,3为卡密新开成功
|
||||||
*/
|
*/
|
||||||
function auth_add($username,$password,$ip,$balance,$uqq,$mail,$appid,$origin,$oid,$aid,&$newkey,&$tips,$tradeinfo = array()){
|
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';
|
include_once __DIR__ . '/function_app.php';
|
||||||
global $db,$G,$MailTips;
|
global $db,$G,$MailTips;
|
||||||
|
|
||||||
|
// P0-05: 密码以 bcrypt 哈希入库。幂等保护:若上游(订单创建点)已哈希则原样保留,
|
||||||
|
// 旧格式明文订单(升级前产生)在此处补哈希
|
||||||
|
if (!wq_is_hashed_password($password)) {
|
||||||
|
$password = wq_hash_password($password);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$appinfo = app_idgetinfo($appid);
|
$appinfo = app_idgetinfo($appid);
|
||||||
if ($appinfo['usetype']=='dqsj'){
|
if ($appinfo['usetype']=='dqsj'){
|
||||||
|
|||||||
@@ -211,6 +211,46 @@ function updateset($name, $value)
|
|||||||
$G['config'][$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
|
* 布尔逻辑型转换为数字0或1
|
||||||
|
|||||||
@@ -81,6 +81,11 @@ function trade_do($tradeinfo){
|
|||||||
}
|
}
|
||||||
if ($tradeinfo['type'] == '4') {
|
if ($tradeinfo['type'] == '4') {
|
||||||
$nowtime = Get_Date();
|
$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']));
|
$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['title'] = '您的代理已成功开通!';
|
||||||
$T['content'][] = 'QQ:'.$tradeinfo['uqq'];
|
$T['content'][] = 'QQ:'.$tradeinfo['uqq'];
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@ SET time_zone = "+00:00";
|
|||||||
CREATE TABLE `sq_admin` (
|
CREATE TABLE `sq_admin` (
|
||||||
`ID` int(11) NOT NULL,
|
`ID` int(11) NOT NULL,
|
||||||
`username` varchar(255) NOT NULL,
|
`username` varchar(255) NOT NULL,
|
||||||
`password` varchar(33) NOT NULL,
|
`password` varchar(255) NOT NULL,
|
||||||
`loginip` varchar(20) NOT NULL,
|
`loginip` varchar(20) NOT NULL,
|
||||||
`logintime` int(11) NOT NULL,
|
`logintime` int(11) NOT NULL,
|
||||||
`qq` varchar(12) NOT NULL,
|
`qq` varchar(12) NOT NULL,
|
||||||
|
|||||||
Reference in New Issue
Block a user