国内流行的内容管理系统(CMS)多端全媒体解决方案 https://www.dedebiz.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

496 lines
15KB

  1. <?php
  2. if (!defined('DEDEINC')) exit('dedebiz');
  3. /**
  4. * 管理员登录类
  5. *
  6. * @version $id:userlogin.class.php 15:59 2010年7月5日 tianya $
  7. * @package DedeBIZ.Libraries
  8. * @copyright Copyright (c) 2022 DedeBIZ.COM
  9. * @license https://www.dedebiz.com/license
  10. * @link https://www.dedebiz.com
  11. */
  12. session_start();
  13. /**
  14. * 检验用户是否有权使用某功能,这个函数是一个回值函数
  15. * CheckPurview函数只是对他回值的一个处理过程
  16. *
  17. * @access public
  18. * @param string $n 功能名称
  19. * @return mix 如果具有则返回TRUE
  20. */
  21. function TestPurview($n)
  22. {
  23. $rs = FALSE;
  24. $purview = $GLOBALS['cuserLogin']->getPurview();
  25. if (preg_match('/admin_AllowAll/i', $purview)) {
  26. return TRUE;
  27. }
  28. if ($n == '') {
  29. return TRUE;
  30. }
  31. if (!isset($GLOBALS['groupRanks'])) {
  32. $GLOBALS['groupRanks'] = explode(' ', $purview);
  33. }
  34. $ns = explode(',', $n);
  35. foreach ($ns as $n) {
  36. //只要找到一个匹配的权限,即可认为用户有权浏览此页面
  37. if ($n == '') {
  38. continue;
  39. }
  40. if (in_array($n, $GLOBALS['groupRanks'])) {
  41. $rs = TRUE;
  42. break;
  43. }
  44. }
  45. return $rs;
  46. }
  47. /**
  48. * 对权限检测后返回操作对话框
  49. *
  50. * @access public
  51. * @param string $n 功能名称
  52. * @return string
  53. */
  54. function CheckPurview($n)
  55. {
  56. if (!TestPurview($n)) {
  57. ShowMsg("您没有权限执行此操作<br><br><a href='javascript:history.go(-1);'>点击返回上一页</a>", 'javascript:;');
  58. exit();
  59. }
  60. }
  61. /**
  62. * 是否没权限限制(超级管理员)
  63. *
  64. * @access public
  65. * @param string
  66. * @return bool
  67. */
  68. function TestAdmin()
  69. {
  70. $purview = $GLOBALS['cuserLogin']->getPurview();
  71. if (preg_match('/admin_AllowAll/i', $purview)) {
  72. return TRUE;
  73. } else {
  74. return FALSE;
  75. }
  76. }
  77. $DedeUserCatalogs = array();
  78. /**
  79. * 检测用户是否有权限操作某栏目
  80. *
  81. * @access public
  82. * @param int $cid 栏目id
  83. * @param string $msg 返回消息
  84. * @return string
  85. */
  86. function CheckCatalog($cid, $msg)
  87. {
  88. global $cfg_admin_channel, $admin_catalogs;
  89. if ($cfg_admin_channel == 'all' || TestAdmin()) {
  90. return TRUE;
  91. }
  92. if (!in_array($cid, $admin_catalogs)) {
  93. ShowMsg(" $msg <br><br><a href='javascript:history.go(-1);'>点击返回上一页</a>", 'javascript:;');
  94. exit();
  95. }
  96. return TRUE;
  97. }
  98. /**
  99. * 发布文档临时附件信息缓存、发文档前先清空附件信息
  100. * 发布文档时涉及的附件保存到缓存里,完成后把它与文档关连
  101. *
  102. * @access public
  103. * @param string $fid 文件ID
  104. * @param string $filename 文件名称
  105. * @return void
  106. */
  107. function AddMyAddon($fid, $filename)
  108. {
  109. $cacheFile = DEDEDATA.'/cache/addon-'.session_id().'.inc';
  110. if (!file_exists($cacheFile)) {
  111. $fp = fopen($cacheFile, 'w');
  112. fwrite($fp, '<'.'?php'."\r\n");
  113. fwrite($fp, "\$myaddons = array();\r\n");
  114. fwrite($fp, "\$maNum = 0;\r\n");
  115. fclose($fp);
  116. }
  117. include($cacheFile);
  118. $fp = fopen($cacheFile, 'a');
  119. $arrPos = $maNum;
  120. $maNum++;
  121. fwrite($fp, "\$myaddons[\$maNum] = array('$fid', '$filename');\r\n");
  122. fwrite($fp, "\$maNum = $maNum;\r\n");
  123. fclose($fp);
  124. }
  125. /**
  126. * 清理附件,如果关连的文档id,先把上一批附件传给这个文档id
  127. *
  128. * @access public
  129. * @param string $aid 文档id
  130. * @param string $title 文档标题
  131. * @return empty
  132. */
  133. function ClearMyAddon($aid = 0, $title = '')
  134. {
  135. global $dsql;
  136. $cacheFile = DEDEDATA.'/cache/addon-'.session_id().'.inc';
  137. $_SESSION['bigfile_info'] = array();
  138. $_SESSION['file_info'] = array();
  139. if (!file_exists($cacheFile)) {
  140. return;
  141. }
  142. //把附件与文档关连
  143. if (!empty($aid)) {
  144. include($cacheFile);
  145. foreach ($myaddons as $addons) {
  146. if (!empty($title)) {
  147. $dsql->ExecuteNoneQuery("Update `#@__uploads` set arcid='$aid',title='$title' where aid='{$addons[0]}'");
  148. } else {
  149. $dsql->ExecuteNoneQuery("Update `#@__uploads` set arcid='$aid' where aid='{$addons[0]}' ");
  150. }
  151. }
  152. }
  153. @unlink($cacheFile);
  154. }
  155. /**
  156. * 登录类
  157. *
  158. * @package userLogin
  159. * @subpackage DedeBIZ.Libraries
  160. * @link https://www.dedebiz.com
  161. */
  162. class userLogin
  163. {
  164. var $userName = '';
  165. var $userPwd = '';
  166. var $userID = '';
  167. var $adminDir = '';
  168. var $userType = '';
  169. var $userChannel = '';
  170. var $userPurview = '';
  171. var $keepUserIDTag = 'dede_admin_id';
  172. var $keepUserTypeTag = 'dede_admin_type';
  173. var $keepUserChannelTag = 'dede_admin_channel';
  174. var $keepUserNameTag = 'dede_admin_name';
  175. var $keepUserPurviewTag = 'dede_admin_purview';
  176. var $keepAdminStyleTag = 'dede_admin_style';
  177. var $adminStyle = 'DedeBIZ';
  178. //php5构造函数
  179. function __construct($admindir = '')
  180. {
  181. global $admin_path;
  182. if (isset($_SESSION[$this->keepUserIDTag])) {
  183. $this->userID = $_SESSION[$this->keepUserIDTag];
  184. $this->userType = $_SESSION[$this->keepUserTypeTag];
  185. $this->userChannel = $_SESSION[$this->keepUserChannelTag];
  186. $this->userName = $_SESSION[$this->keepUserNameTag];
  187. $this->userPurview = $_SESSION[$this->keepUserPurviewTag];
  188. $this->adminStyle = $_SESSION[$this->keepAdminStyleTag];
  189. }
  190. if ($admindir != '') {
  191. $this->adminDir = $admindir;
  192. } else {
  193. $this->adminDir = $admin_path;
  194. }
  195. }
  196. function userLogin($admindir = '')
  197. {
  198. $this->__construct($admindir);
  199. }
  200. /**
  201. * 检验用户是否正确
  202. *
  203. * @access public
  204. * @param string $username 用户名
  205. * @param string $userpwd 密码
  206. * @return string
  207. */
  208. function checkUser($username, $userpwd)
  209. {
  210. global $dsql;
  211. //只允许用户名和密码用0-9,a-z,A-Z,'@','_','.','-'这些字符
  212. $this->userName = preg_replace("/[^0-9a-zA-Z_@!\.-]/", '', $username);
  213. $this->userPwd = preg_replace("/[^0-9a-zA-Z_@!\.-]/", '', $userpwd);
  214. $pwd = substr(md5($this->userPwd), 5, 20);
  215. $dsql->SetQuery("SELECT admin.*,atype.purviews FROM `#@__admin` admin LEFT JOIN `#@__admintype` atype ON atype.`rank`=admin.usertype WHERE admin.userid LIKE '".$this->userName."' LIMIT 0,1");
  216. $dsql->Execute();
  217. $row = $dsql->GetObject();
  218. if (!isset($row->pwd)) {
  219. return -1;
  220. } else if (!empty($row->pwd_new) && !password_verify($this->userPwd, $row->pwd_new)) {
  221. $this->loginError($row->id);
  222. return -2;
  223. } else if (!empty($row->pwd) && $pwd != $row->pwd) {
  224. $this->loginError($row->id);
  225. return -2;
  226. } else {
  227. $upsql = "";
  228. if (empty($row->pwd_new) && function_exists('password_hash')) {
  229. //升级密码
  230. $newpwd = password_hash($this->userPwd, PASSWORD_BCRYPT);
  231. $upsql .= ",pwd='',pwd_new='{$newpwd}'";
  232. }
  233. $loginip = GetIP();
  234. $this->userID = $row->id;
  235. $this->userType = $row->usertype;
  236. $this->userChannel = $row->typeid;
  237. $this->userName = $row->uname;
  238. $this->userPurview = $row->purviews;
  239. $inquery = "UPDATE `#@__admin` SET loginip='$loginip',logintime='".time()."'{$upsql},loginerr=0 WHERE id='".$row->id."'";
  240. $dsql->ExecuteNoneQuery($inquery);
  241. $sql = "UPDATE `#@__member` SET logintime=".time().", loginip='$loginip' WHERE mid=".$row->id;
  242. $dsql->ExecuteNoneQuery($sql);
  243. return 1;
  244. }
  245. }
  246. /**
  247. * 是否需要验证码
  248. *
  249. * @param mixed $username
  250. * @return bool
  251. */
  252. function isNeedCheckCode($username)
  253. {
  254. $num = $this->getLoginError($username);
  255. return $num >= 3 ? true : false;
  256. }
  257. /**
  258. * 1分钟以内登录错误的次数
  259. *
  260. * @param mixed $username
  261. * @return int 登录错误次数
  262. */
  263. function getLoginError($username)
  264. {
  265. global $dsql;
  266. if (!TableHasField("#@__admin", "loginerr")) {
  267. return 0;
  268. }
  269. $this->userName = preg_replace("/[^0-9a-zA-Z_@!\.-]/", '', $username);
  270. $row = $dsql->GetOne("SELECT loginerr,logintime FROM `#@__admin` WHERE userid LIKE '$this->userName'");
  271. if (is_array($row)) {
  272. //1分钟内如果输错3次则需要验证码
  273. return (time() - (int)$row['logintime']) < 60 ? (int)$row['loginerr'] : 0;
  274. } else {
  275. return -1;
  276. }
  277. }
  278. /**
  279. * 记录登录错误
  280. *
  281. * @return void
  282. */
  283. function loginError($adminid)
  284. {
  285. global $dsql;
  286. $loginip = GetIP();
  287. $inquery = "UPDATE `#@__admin` SET loginip='$loginip',logintime='".time()."',loginerr=loginerr+1 WHERE id='".$adminid."'";
  288. $dsql->ExecuteNoneQuery($inquery);
  289. }
  290. /**
  291. * 保持用户的会话状态
  292. *
  293. * @access public
  294. * @return int 成功返回 1,失败返回 -1
  295. */
  296. function keepUser()
  297. {
  298. if ($this->userID != '' && $this->userType != '') {
  299. global $admincachefile, $adminstyle;
  300. if (empty($adminstyle)) $adminstyle = 'DedeBIZ';
  301. @session_register($this->keepUserIDTag);
  302. $_SESSION[$this->keepUserIDTag] = $this->userID;
  303. @session_register($this->keepUserTypeTag);
  304. $_SESSION[$this->keepUserTypeTag] = $this->userType;
  305. @session_register($this->keepUserChannelTag);
  306. $_SESSION[$this->keepUserChannelTag] = $this->userChannel;
  307. @session_register($this->keepUserNameTag);
  308. $_SESSION[$this->keepUserNameTag] = $this->userName;
  309. @session_register($this->keepUserPurviewTag);
  310. $_SESSION[$this->keepUserPurviewTag] = $this->userPurview;
  311. @session_register($this->keepAdminStyleTag);
  312. $_SESSION[$this->keepAdminStyleTag] = $adminstyle;
  313. PutCookie('DedeUserID', $this->userID, 3600 * 24, '/');
  314. PutCookie('DedeLoginTime', time(), 3600 * 24, '/');
  315. $this->ReWriteAdminChannel();
  316. return 1;
  317. } else {
  318. return -1;
  319. }
  320. }
  321. /**
  322. * 重写用户权限栏目
  323. *
  324. * @access public
  325. * @return void
  326. */
  327. function ReWriteAdminChannel()
  328. {
  329. //$this->userChannel
  330. $cacheFile = DEDEDATA.'/cache/admincat_'.$this->userID.'.inc';
  331. //管理员管理的栏目列表
  332. $typeid = trim($this->userChannel);
  333. if (empty($typeid) || $this->getUserType() >= 10) {
  334. $firstConfig = "\$cfg_admin_channel = 'all';\r\n\$admin_catalogs = array();\r\n";
  335. } else {
  336. $firstConfig = "\$cfg_admin_channel = 'array';\r\n";
  337. }
  338. $fp = fopen($cacheFile, 'w');
  339. fwrite($fp, '<'.'?php'."\r\n");
  340. fwrite($fp, $firstConfig);
  341. if (!empty($typeid)) {
  342. $typeids = explode(',', $typeid);
  343. $typeid = '';
  344. foreach ($typeids as $tid) {
  345. $typeid .= ($typeid == '' ? GetSonIdsUL($tid) : ','.GetSonIdsUL($tid));
  346. }
  347. $typeids = explode(',', $typeid);
  348. $typeidsnew = array_unique($typeids);
  349. $typeid = join(',', $typeidsnew);
  350. fwrite($fp, "\$admin_catalogs = array($typeid);\r\n");
  351. }
  352. fwrite($fp, '?'.'>');
  353. fclose($fp);
  354. }
  355. /**
  356. * 结束用户的会话状态
  357. *
  358. * @access public
  359. * @return void
  360. */
  361. function exitUser()
  362. {
  363. ClearMyAddon();
  364. @session_unregister($this->keepUserIDTag);
  365. @session_unregister($this->keepUserTypeTag);
  366. @session_unregister($this->keepUserChannelTag);
  367. @session_unregister($this->keepUserNameTag);
  368. @session_unregister($this->keepUserPurviewTag);
  369. DropCookie('dedeAdmindir');
  370. DropCookie('DedeUserID');
  371. DropCookie('DedeLoginTime');
  372. $_SESSION = array();
  373. }
  374. /**
  375. * 获得用户管理栏目的值
  376. *
  377. * @access public
  378. * @return array
  379. */
  380. function getUserChannel()
  381. {
  382. if ($this->userChannel != '') {
  383. return $this->userChannel;
  384. } else {
  385. return '';
  386. }
  387. }
  388. /**
  389. * 获得用户的权限值
  390. *
  391. * @access public
  392. * @return int
  393. */
  394. function getUserType()
  395. {
  396. if ($this->userType != '') {
  397. return $this->userType;
  398. } else {
  399. return -1;
  400. }
  401. }
  402. /**
  403. * 获取用户权限值
  404. *
  405. * @access public
  406. * @return int
  407. */
  408. function getUserRank()
  409. {
  410. return $this->getUserType();
  411. }
  412. /**
  413. * 获得用户的id
  414. *
  415. * @access public
  416. * @return int
  417. */
  418. function getUserID()
  419. {
  420. if ($this->userID != '') {
  421. return $this->userID;
  422. } else {
  423. return -1;
  424. }
  425. }
  426. /**
  427. * 获得用户的名称
  428. *
  429. * @access public
  430. * @return string
  431. */
  432. function getUserName()
  433. {
  434. if ($this->userName != '') {
  435. return $this->userName;
  436. } else {
  437. return -1;
  438. }
  439. }
  440. /**
  441. * 用户权限表
  442. *
  443. * @access public
  444. * @return string
  445. */
  446. function getPurview()
  447. {
  448. return $this->userPurview;
  449. }
  450. }
  451. /**
  452. * 获得某id的所有下级id
  453. *
  454. * @access public
  455. * @param int $id 栏目id
  456. * @param int $channel 栏目id
  457. * @param int $addthis 是否加入当前这个栏目
  458. * @return string
  459. */
  460. function GetSonIdsUL($id, $channel = 0, $addthis = TRUE)
  461. {
  462. global $cfg_Cs;
  463. $GLOBALS['idArray'] = array();
  464. if (!is_array($cfg_Cs)) {
  465. require_once(DEDEDATA."/cache/inc_catalog_base.inc");
  466. }
  467. GetSonIdsLogicUL($id, $cfg_Cs, $channel, $addthis);
  468. $rquery = join(',', $GLOBALS['idArray']);
  469. return $rquery;
  470. }
  471. /**
  472. * 递归逻辑
  473. *
  474. * @access public
  475. * @param int $id 栏目id
  476. * @param array $sArr 缓存数组
  477. * @param int $channel 栏目id
  478. * @param int $addthis 是否加入当前这个栏目
  479. * @return string
  480. */
  481. function GetSonIdsLogicUL($id, $sArr, $channel = 0, $addthis = FALSE)
  482. {
  483. if ($id != 0 && $addthis) {
  484. $GLOBALS['idArray'][$id] = $id;
  485. }
  486. foreach ($sArr as $k => $v) {
  487. if ($v[0] == $id && ($channel == 0 || $v[1] == $channel)) {
  488. GetSonIdsLogicUL($k, $sArr, $channel, TRUE);
  489. }
  490. }
  491. }