Authcompany.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. <?php
  2. namespace app\common\library;
  3. use app\common\model\PcAdmin as User;
  4. use fast\Random;
  5. use fast\Tree;
  6. use think\Config;
  7. use think\Db;
  8. use think\Exception;
  9. use think\Hook;
  10. use think\Request;
  11. use think\Validate;
  12. class Authcompany
  13. {
  14. protected static $instance = null;
  15. protected $_error = '';
  16. protected $_logined = false;
  17. protected $_user = null;
  18. protected $_token = '';
  19. //Token默认有效时长
  20. protected $keeptime = 2592000;
  21. protected $requestUri = '';
  22. protected $rules = [];
  23. //默认配置
  24. protected $config = [];
  25. protected $options = [];
  26. protected $allowFields = [
  27. 'id',
  28. 'username',
  29. 'nickname',
  30. 'avatar',
  31. 'company_id',
  32. ];
  33. public function __construct($options = [])
  34. {
  35. if ($config = Config::get('company')) {
  36. $this->config = array_merge($this->config, $config);
  37. }
  38. $this->options = array_merge($this->config, $options);
  39. }
  40. /**
  41. *
  42. * @param array $options 参数
  43. * @return Auth
  44. */
  45. public static function instance($options = [])
  46. {
  47. if (is_null(self::$instance)) {
  48. self::$instance = new static($options);
  49. }
  50. return self::$instance;
  51. }
  52. /**
  53. * 获取User模型
  54. * @return User
  55. */
  56. public function getUser()
  57. {
  58. return $this->_user;
  59. }
  60. /**
  61. * 兼容调用user模型的属性
  62. *
  63. * @param string $name
  64. * @return mixed
  65. */
  66. public function __get($name)
  67. {
  68. return $this->_user ? $this->_user->$name : null;
  69. }
  70. /**
  71. * 兼容调用user模型的属性
  72. */
  73. public function __isset($name)
  74. {
  75. return isset($this->_user) ? isset($this->_user->$name) : false;
  76. }
  77. /**
  78. * 根据Token初始化
  79. *
  80. * @param string $token Token
  81. * @return boolean
  82. */
  83. public function init($token)
  84. {
  85. if ($this->_logined) {
  86. return true;
  87. }
  88. if ($this->_error) {
  89. return false;
  90. }
  91. $data = Tokencompany::get($token);
  92. if (!$data) {
  93. return false;
  94. }
  95. $user_id = intval($data['user_id']);
  96. if ($user_id > 0) {
  97. $user = User::get($user_id);
  98. if (!$user) {
  99. $this->setError('Account not exist');
  100. return false;
  101. }
  102. if ($user['status'] != 1) {
  103. $this->setError('Account is locked');
  104. return false;
  105. }
  106. $this->_user = $user;
  107. $this->_logined = true;
  108. $this->_token = $token;
  109. //初始化成功的事件
  110. Hook::listen("company_init_successed", $this->_user);
  111. return true;
  112. } else {
  113. $this->setError('You are not logged in');
  114. return false;
  115. }
  116. }
  117. /**
  118. * 用户登录
  119. *
  120. * @param string $account 账号,用户名、邮箱、手机号
  121. * @param string $password 密码
  122. * @return boolean
  123. */
  124. public function login($account, $password)
  125. {
  126. $field = 'username';
  127. $user = User::get([$field => $account]);
  128. if (!$user) {
  129. $this->setError('Account is incorrect');
  130. return false;
  131. }
  132. if ($user->status != 1) {
  133. $this->setError('Account is locked');
  134. return false;
  135. }
  136. if (Config::get('pcadmin.login_failure_retry') && $user->loginfailure >= 10 && time() - $user->updatetime < 86400) {
  137. $this->setError('Please try again after 1 day');
  138. return false;
  139. }
  140. if ($user->password != $this->getEncryptPassword($password, $user->salt)) {
  141. $user->loginfailure++;
  142. $this->setError('Password is incorrect');
  143. return false;
  144. }
  145. //直接登录会员
  146. return $this->direct($user->id);
  147. }
  148. /**
  149. * 退出
  150. *
  151. * @return boolean
  152. */
  153. public function logout()
  154. {
  155. if (!$this->_logined) {
  156. $this->setError('You are not logged in');
  157. return false;
  158. }
  159. //设置登录标识
  160. $this->_logined = false;
  161. //删除Token
  162. Tokencompany::delete($this->_token);
  163. //退出成功的事件
  164. Hook::listen("user_logout_successed", $this->_user);
  165. return true;
  166. }
  167. /**
  168. * 修改密码
  169. * @param string $newpassword 新密码
  170. * @param string $oldpassword 旧密码
  171. * @param bool $ignoreoldpassword 忽略旧密码
  172. * @return boolean
  173. */
  174. public function changepwd($newpassword, $oldpassword = '', $ignoreoldpassword = false)
  175. {
  176. if (!$this->_logined) {
  177. $this->setError('You are not logged in');
  178. return false;
  179. }
  180. //判断旧密码是否正确
  181. if ($this->_user->password == $this->getEncryptPassword($oldpassword, $this->_user->salt) || $ignoreoldpassword) {
  182. Db::startTrans();
  183. try {
  184. $salt = Random::alnum();
  185. $newpassword = $this->getEncryptPassword($newpassword, $salt);
  186. $this->_user->save(['loginfailure' => 0, 'password' => $newpassword, 'salt' => $salt]);
  187. Tokencompany::delete($this->_token);
  188. //修改密码成功的事件
  189. Hook::listen("company_changepwd_successed", $this->_user);
  190. Db::commit();
  191. } catch (Exception $e) {
  192. Db::rollback();
  193. $this->setError($e->getMessage());
  194. return false;
  195. }
  196. return true;
  197. } else {
  198. $this->setError('Password is incorrect');
  199. return false;
  200. }
  201. }
  202. /**
  203. * 直接登录账号
  204. * @param int $user_id
  205. * @return boolean
  206. */
  207. public function direct($user_id)
  208. {
  209. $user = User::get($user_id);
  210. if ($user) {
  211. Db::startTrans();
  212. try {
  213. $ip = request()->ip();
  214. $time = time();
  215. $user->loginfailure = 0;
  216. $user->logintime = $time;
  217. $user->loginip = $ip;
  218. $user->save();
  219. $this->_user = $user;
  220. $this->_token = Random::uuid();
  221. Tokencompany::set($this->_token, $user->id, $this->keeptime);
  222. $this->_logined = true;
  223. //登录成功的事件
  224. Hook::listen("company_login_successed", $this->_user);
  225. Db::commit();
  226. } catch (Exception $e) {
  227. Db::rollback();
  228. $this->setError($e->getMessage());
  229. return false;
  230. }
  231. return true;
  232. } else {
  233. return false;
  234. }
  235. }
  236. /**
  237. * 检测是否是否有对应权限
  238. * @param string $path 控制器/方法
  239. * @param string $module 模块 默认为当前模块
  240. * @return boolean
  241. */
  242. public function check($path = null, $module = null)
  243. {
  244. if (!$this->_logined) {
  245. return false;
  246. }
  247. $ruleList = $this->getRuleList();
  248. $rules = [];
  249. foreach ($ruleList as $k => $v) {
  250. $rules[] = $v['name'];
  251. }
  252. $url = ($module ? $module : request()->module()) . '/' . (is_null($path) ? $this->getRequestUri() : $path);
  253. $url = strtolower(str_replace('.', '/', $url));
  254. return in_array($url, $rules) ? true : false;
  255. }
  256. /**
  257. * 判断是否登录
  258. * @return boolean
  259. */
  260. public function isLogin()
  261. {
  262. if ($this->_logined) {
  263. return true;
  264. }
  265. return false;
  266. }
  267. /**
  268. * 获取当前Token
  269. * @return string
  270. */
  271. public function getToken()
  272. {
  273. return $this->_token;
  274. }
  275. /**
  276. * 获取会员基本信息
  277. */
  278. public function getUserinfo_simple()
  279. {
  280. $data = $this->_user->toArray();
  281. $allowFields = $this->getAllowFields();
  282. $userinfo = array_intersect_key($data, array_flip($allowFields));
  283. $userinfo = array_merge($userinfo, Tokencompany::get($this->_token));
  284. //追加
  285. $userinfo['avatar'] = localpath_to_netpath($userinfo['avatar']);
  286. return $userinfo;
  287. }
  288. /**
  289. * 获取会员基本信息
  290. */
  291. public function getUserinfo()
  292. {
  293. $data = $this->_user->toArray();
  294. $allowFields = $this->getAllowFields();
  295. $userinfo = array_intersect_key($data, array_flip($allowFields));
  296. $userinfo = array_merge($userinfo, Tokencompany::get($this->_token));
  297. //追加
  298. $userinfo['avatar'] = localpath_to_netpath($userinfo['avatar']);
  299. //追加公司信息
  300. $userinfo['company'] = Db::name('company')->field('id,companyname')->where('id',$userinfo['company_id'])->find();
  301. return $userinfo;
  302. }
  303. /**
  304. * 获取当前请求的URI
  305. * @return string
  306. */
  307. public function getRequestUri()
  308. {
  309. return $this->requestUri;
  310. }
  311. /**
  312. * 设置当前请求的URI
  313. * @param string $uri
  314. */
  315. public function setRequestUri($uri)
  316. {
  317. $this->requestUri = $uri;
  318. }
  319. /**
  320. * 获取允许输出的字段
  321. * @return array
  322. */
  323. public function getAllowFields()
  324. {
  325. return $this->allowFields;
  326. }
  327. /**
  328. * 设置允许输出的字段
  329. * @param array $fields
  330. */
  331. public function setAllowFields($fields)
  332. {
  333. $this->allowFields = $fields;
  334. }
  335. /**
  336. * 删除一个指定会员
  337. * @param int $user_id 会员ID
  338. * @return boolean
  339. */
  340. public function delete($user_id)
  341. {
  342. $user = User::get($user_id);
  343. if (!$user) {
  344. return false;
  345. }
  346. Db::startTrans();
  347. try {
  348. // 删除会员
  349. User::destroy($user_id);
  350. // 删除会员指定的所有Token
  351. Tokencompany::clear($user_id);
  352. Hook::listen("company_delete_successed", $user);
  353. Db::commit();
  354. } catch (Exception $e) {
  355. Db::rollback();
  356. $this->setError($e->getMessage());
  357. return false;
  358. }
  359. return true;
  360. }
  361. /**
  362. * 获取密码加密后的字符串
  363. * @param string $password 密码
  364. * @param string $salt 密码盐
  365. * @return string
  366. */
  367. public function getEncryptPassword($password, $salt = '')
  368. {
  369. return md5(md5($password) . $salt);
  370. }
  371. /**
  372. * 检测当前控制器和方法是否匹配传递的数组
  373. *
  374. * @param array $arr 需要验证权限的数组
  375. * @return boolean
  376. */
  377. public function match($arr = [])
  378. {
  379. $request = Request::instance();
  380. $arr = is_array($arr) ? $arr : explode(',', $arr);
  381. if (!$arr) {
  382. return false;
  383. }
  384. $arr = array_map('strtolower', $arr);
  385. // 是否存在
  386. if (in_array(strtolower($request->action()), $arr) || in_array('*', $arr)) {
  387. return true;
  388. }
  389. // 没找到匹配
  390. return false;
  391. }
  392. /**
  393. * 设置会话有效时间
  394. * @param int $keeptime 默认为永久
  395. */
  396. public function keeptime($keeptime = 0)
  397. {
  398. $this->keeptime = $keeptime;
  399. }
  400. /**
  401. * 设置错误信息
  402. *
  403. * @param string $error 错误信息
  404. * @return Auth
  405. */
  406. public function setError($error)
  407. {
  408. $this->_error = $error;
  409. return $this;
  410. }
  411. /**
  412. * 获取错误信息
  413. * @return string
  414. */
  415. public function getError()
  416. {
  417. return $this->_error ? __($this->_error) : '';
  418. }
  419. }