UserService.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. <?php
  2. namespace App\Module\User\Services;
  3. use App\Module\App\Mnemon;
  4. use App\Module\App\SessionApp;
  5. use App\Module\Ulogic\Model\UserBans;
  6. use App\Module\Ulogic\Model\UserWord;
  7. use App\Module\User\Model\User;
  8. use Illuminate\Support\Facades\Cache;
  9. use Illuminate\Support\Facades\DB;
  10. class UserService
  11. {
  12. // 默认头像
  13. const AVATAR = 'https://www.api.xuyoo.cc/images/default_avatar.jpg';
  14. // 登录错误次数key
  15. const LOGIN_ERROR_NUM = 'LOGIN_ERROR_NUM_';
  16. // 登录错误次数最大值
  17. const ERROR_NUM = 5;
  18. /**
  19. * @param $mobile
  20. * @return bool
  21. * 查询用户信息
  22. */
  23. public static function getUserByMobile($mobile)
  24. {
  25. $data = User::query()->where('mobile', $mobile)->first();
  26. if (!$data || !$data->password) {
  27. return false;
  28. }
  29. return true;
  30. }
  31. /**
  32. * @param $mobile
  33. * @return \App\Module\Ulogic\Unit\User|array|false
  34. * @throws \\Exception\LogicException
  35. * 注册
  36. */
  37. public static function register($mobile)
  38. {
  39. // 判断手机号是否已存在
  40. $model = User::getUserInfoByCondition('mobile', $mobile);
  41. if (!$model) {
  42. // user表插入数据,返回token
  43. $model = User::createUser($mobile, self::AVATAR);
  44. if (!$model) {
  45. return false;
  46. }
  47. }
  48. // 生成token
  49. $data = SessionApp::setLogin($model, true);
  50. return $data;
  51. }
  52. /**
  53. * @param $inviteCode
  54. * @return array|false
  55. * 获取邀请信息
  56. */
  57. public static function getInviteInfo($inviteCode)
  58. {
  59. $data = User::getUserInfoByCondition('invite_code', $inviteCode);
  60. if (empty($data)) {
  61. return false;
  62. }
  63. return [
  64. 'nickname' => $data['nickname'],
  65. 'avatar' => $data['avatar'],
  66. ];
  67. }
  68. /**
  69. * @param $mobile
  70. * @param $password
  71. * @return \App\Module\Ulogic\Unit\User|array|false
  72. * @throws \FurqanSiddiqui\BIP39\Exception\Bip39MnemonicException
  73. * @throws \\Exception\LogicException
  74. * 登录
  75. */
  76. public static function login($data)
  77. {
  78. $mobile = $data['mobile'];
  79. $password = $data['password'];
  80. $userData = User::getUserInfoByCondition('mobile', $mobile);
  81. if (empty($userData)) {
  82. throw new ValidateException(null, '用户不存在');
  83. }
  84. // 验证封禁状态
  85. if ($userData->is_prohibit != 0) {
  86. return [
  87. 'isProhibit' => 1,
  88. 'token' => ''
  89. ];
  90. }
  91. $check = self::checkPassword($userData, $password);
  92. $key = self::LOGIN_ERROR_NUM.$userData->user_id;
  93. if (!$check) {
  94. // 记录用户错误次数
  95. if (Cache::has($key)) {
  96. Cache::increment($key);
  97. // 错误达到5次封号
  98. $errorNum = Cache::get($key);
  99. if ($errorNum >= self::ERROR_NUM) {
  100. DB::beginTransaction();
  101. try {
  102. // 封号
  103. UserBans::create($userData->user_id, 1, 0, time() + 86400);
  104. // 修改用户窗台
  105. User::updateByUserId($userData->user_id, 'is_prohibit', '1');
  106. DB::commit();
  107. throw new ValidateException(null, '助记词错误,已临时冻结,请在24小时后尝试');
  108. } catch (\Exception $e) {
  109. DB::rollBack();
  110. throw new ValidateException(null, $e->getMessage());
  111. }
  112. }
  113. } else {
  114. Cache::put($key, 1);
  115. }
  116. throw new ValidateException(null, '登录失败');
  117. }
  118. // 设置token
  119. Cache::delete($key);
  120. return SessionApp::setLogin($userData, true);
  121. }
  122. /**
  123. * 根据UserId登陆
  124. *
  125. * @param $user_id
  126. * @return \App\Module\Ulogic\Unit\User|array
  127. * @throws \\Exception\LogicException
  128. */
  129. public static function loginById($user_id)
  130. {
  131. $userData = User::query()->find($user_id);
  132. return SessionApp::setLogin($userData, true);
  133. }
  134. /**
  135. * @param $data
  136. * @return array
  137. * @throws ValidateException
  138. * 获取封禁信息
  139. */
  140. public static function getBanInfo($data)
  141. {
  142. $userData = User::getUserInfoByCondition('mobile', $data['mobile']);
  143. $check = self::checkPassword($userData, $data['password']);
  144. if (!$check) {
  145. throw new ValidateException(null, '助记词错误');
  146. }
  147. if ($userData->is_prohibit == 0) {
  148. throw new ValidateException(null, '该用户状态正常');
  149. }
  150. $banInfo = UserBans::getRow($userData->user_id, $userData->is_prohibit);
  151. $diff = $banInfo->end_time - time();
  152. $endTime = 0;
  153. if ($diff > 0) {
  154. $endTime = gmdate('h:i:s', $diff);
  155. }
  156. return [
  157. 'type' => $banInfo->type,
  158. 'ban_time' => $banInfo->created_at->toDateTimeString(),
  159. 'end_time' => $endTime,
  160. ];
  161. }
  162. /**
  163. * @param $userData
  164. * @param $password
  165. * @return bool|\FurqanSiddiqui\BIP39\Mnemonic|string
  166. * 验证助记词
  167. */
  168. private static function checkPassword($userData, $password)
  169. {
  170. // 判断新老用户(user_word表里有没有记录)
  171. $userWord = UserWord::getData($userData->user_id);
  172. if (empty($userWord)) {
  173. // 新用户 BIP39验证
  174. $check = Mnemon::wordsToMnemonic($password, $userData->user_id, false);
  175. } else {
  176. // 老用户 md5验证
  177. $password = strtolower($password);
  178. $password = str_replace(",", '","', $password);
  179. $password = '["'.$password.'"]';
  180. $password = md5(md5($password));
  181. $check = false;
  182. if ($password === $userData->password) {
  183. $check = true;
  184. }
  185. }
  186. return $check;
  187. }
  188. /**
  189. * @param $userId
  190. * @return User|false
  191. * 获取用户信息(user-id)
  192. */
  193. public static function getInfoByUserId($userId)
  194. {
  195. $data = User::query()->where('user_id', $userId)->first();
  196. if (!$data || !$data->password) {
  197. return false;
  198. }
  199. return $data;
  200. }
  201. /**
  202. * @param $userId
  203. * @param $password
  204. * @return mixed
  205. * 修改安全密码
  206. */
  207. public static function resetSecretPassword($userId, $password)
  208. {
  209. // 定义查询条件(唯一标识字段)
  210. $conditions = ['user_id' => $userId];
  211. // 需要更新或插入的数据
  212. $data = [
  213. 'secret_password' => password_hash($password, PASSWORD_DEFAULT)
  214. ];
  215. $res = UserPassword::updateOrCreate($conditions,$data);
  216. // 输出结果
  217. if ($res->id) {
  218. return true;
  219. } else {
  220. return false;
  221. }
  222. }
  223. /**
  224. * @param $userId
  225. * @return bool
  226. * 查询用户是否绑定谷歌验证器
  227. */
  228. public static function isBindGoogle($userId)
  229. {
  230. $userPasswordData = UserPassword::query()->where('user_id', $userId)->first();
  231. if (!$userPasswordData->google2fa_secret) {
  232. return false;
  233. }
  234. return true;
  235. }
  236. /**
  237. * @param $userId
  238. * @param $password
  239. * @return bool
  240. * 验证用户安全密码
  241. */
  242. public static function checkSecretPassword($userId, $password)
  243. {
  244. $userPasswordData = UserPassword::query()
  245. ->where('user_id', $userId)
  246. ->first();
  247. if (!$userPasswordData) {
  248. return false;
  249. }
  250. if (!password_verify($password, $userPasswordData->secret_password)) {
  251. return false;
  252. }
  253. return true;
  254. }
  255. }