AuthController.php 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Components\Helpers;
  4. use App\Components\IP;
  5. use App\Mail\activeUser;
  6. use App\Mail\resetPassword;
  7. use App\Mail\sendVerifyCode;
  8. use App\Models\EmailFilter;
  9. use App\Models\Invite;
  10. use App\Models\User;
  11. use App\Models\UserLoginLog;
  12. use App\Models\Verify;
  13. use App\Models\VerifyCode;
  14. use App\Services\UserService;
  15. use Auth;
  16. use Cache;
  17. use Captcha;
  18. use Cookie;
  19. use Hash;
  20. use Illuminate\Http\RedirectResponse;
  21. use Illuminate\Http\Request;
  22. use Log;
  23. use Mail;
  24. use Redirect;
  25. use Response;
  26. use Session;
  27. use Str;
  28. use Validator;
  29. /**
  30. * 认证控制器
  31. *
  32. * Class AuthController
  33. *
  34. * @package App\Http\Controllers
  35. */
  36. class AuthController extends Controller
  37. {
  38. // 登录
  39. public function login(Request $request)
  40. {
  41. if ($request->isMethod('POST')) {
  42. $validator = Validator::make(
  43. $request->all(),
  44. [
  45. 'email' => 'required|email',
  46. 'password' => 'required',
  47. ],
  48. [
  49. 'email.required' => trans('auth.email_null'),
  50. 'password.required' => trans('auth.password_null'),
  51. ]
  52. );
  53. if ($validator->fails()) {
  54. return Redirect::back()->withInput()->withErrors(
  55. $validator->errors()
  56. );
  57. }
  58. $email = $request->input('email');
  59. $password = $request->input('password');
  60. $remember = $request->input('remember');
  61. // 是否校验验证码
  62. $captcha = $this->check_captcha($request);
  63. if ($captcha != false) {
  64. return $captcha;
  65. }
  66. // 验证账号并创建会话
  67. if ( ! Auth::attempt(
  68. ['email' => $email, 'password' => $password],
  69. $remember
  70. )) {
  71. return Redirect::back()->withInput()->withErrors(
  72. trans('auth.login_error')
  73. );
  74. }
  75. $user = Auth::getUser();
  76. if ( ! $user) {
  77. return Redirect::back()->withInput()->withErrors(
  78. trans('auth.login_error')
  79. );
  80. }
  81. // 校验普通用户账号状态
  82. if ( ! $user->is_admin) {
  83. if ($user->status < 0) {
  84. Auth::logout(); // 强制销毁会话,因为Auth::attempt的时候会产生会话
  85. return Redirect::back()->withInput()->withErrors(
  86. trans(
  87. 'auth.login_ban',
  88. ['email' => sysConfig('webmaster_email')]
  89. )
  90. );
  91. }
  92. if ($user->status == 0 && sysConfig('is_activate_account')) {
  93. Auth::logout(); // 强制销毁会话,因为Auth::attempt的时候会产生会话
  94. return Redirect::back()
  95. ->withInput()
  96. ->withErrors(
  97. trans(
  98. 'auth.active_tip'
  99. ) . '<a href="/activeUser?email=' . $email . '" target="_blank"><span style="color:#000">【' . trans(
  100. 'auth.active_account'
  101. ) . '】</span></a>'
  102. );
  103. }
  104. }
  105. // 写入登录日志
  106. $this->addUserLoginLog($user->id, IP::getClientIp());
  107. // 更新登录信息
  108. Auth::getUser()->update(['last_login' => time()]);
  109. // 根据权限跳转
  110. if ($user->is_admin) {
  111. return Redirect::to('admin');
  112. }
  113. return Redirect::to('/');
  114. }
  115. if (Auth::check()) {
  116. if (Auth::getUser()->is_admin) {
  117. return Redirect::to('admin');
  118. }
  119. return Redirect::to('/');
  120. }
  121. return view('auth.login');
  122. }
  123. // 校验验证码
  124. private function check_captcha($request)
  125. {
  126. switch (sysConfig('is_captcha')) {
  127. case 1: // 默认图形验证码
  128. if ( ! Captcha::check($request->input('captcha'))) {
  129. return Redirect::back()->withInput()->withErrors(
  130. trans('auth.captcha_error')
  131. );
  132. }
  133. break;
  134. case 2: // Geetest
  135. $validator = Validator::make(
  136. $request->all(),
  137. [
  138. 'geetest_challenge' => 'required|geetest',
  139. ],
  140. [
  141. 'geetest' => trans('auth.captcha_fail'),
  142. ]
  143. );
  144. if ($validator->fails()) {
  145. return Redirect::back()->withInput()->withErrors(
  146. trans('auth.captcha_fail')
  147. );
  148. }
  149. break;
  150. case 3: // Google reCAPTCHA
  151. $validator = Validator::make(
  152. $request->all(),
  153. [
  154. 'g-recaptcha-response' => 'required|NoCaptcha',
  155. ]
  156. );
  157. if ($validator->fails()) {
  158. return Redirect::back()->withInput()->withErrors(
  159. trans('auth.captcha_fail')
  160. );
  161. }
  162. break;
  163. case 4: // hCaptcha
  164. $validator = Validator::make(
  165. $request->all(),
  166. [
  167. 'h-captcha-response' => 'required|HCaptcha',
  168. ]
  169. );
  170. if ($validator->fails()) {
  171. return Redirect::back()->withInput()->withErrors(
  172. trans('auth.captcha_fail')
  173. );
  174. }
  175. break;
  176. default: // 不启用验证码
  177. break;
  178. }
  179. return 0;
  180. }
  181. /**
  182. * 添加用户登录日志
  183. *
  184. * @param int $userId 用户ID
  185. * @param string $ip IP地址
  186. */
  187. private function addUserLoginLog(int $userId, string $ip): void
  188. {
  189. $ipLocation = IP::getIPInfo($ip);
  190. if (empty($ipLocation) || empty($ipLocation['country'])) {
  191. Log::warning("获取IP信息异常:" . $ip);
  192. }
  193. $log = new UserLoginLog();
  194. $log->user_id = $userId;
  195. $log->ip = $ip;
  196. $log->country = $ipLocation['country'] ?? '';
  197. $log->province = $ipLocation['province'] ?? '';
  198. $log->city = $ipLocation['city'] ?? '';
  199. $log->county = $ipLocation['county'] ?? '';
  200. $log->isp = $ipLocation['isp'] ?? ($ipLocation['organization'] ?? '');
  201. $log->area = $ipLocation['area'] ?? '';
  202. $log->save();
  203. }
  204. // 退出
  205. public function logout(): RedirectResponse
  206. {
  207. Auth::logout();
  208. return Redirect::to('login');
  209. }
  210. // 注册
  211. public function register(Request $request)
  212. {
  213. $cacheKey = 'register_times_' . md5(IP::getClientIp()); // 注册限制缓存key
  214. if ($request->isMethod('POST')) {
  215. $validator = Validator::make(
  216. $request->all(),
  217. [
  218. 'username' => 'required',
  219. 'email' => 'required|email|unique:user',
  220. 'password' => 'required|min:6',
  221. 'confirmPassword' => 'required|same:password',
  222. 'term' => 'accepted',
  223. ],
  224. [
  225. 'username.required' => trans('auth.email_null'),
  226. 'email.required' => trans('auth.email_null'),
  227. 'email.email' => trans(
  228. 'auth.email_legitimate'
  229. ),
  230. 'email.unique' => trans('auth.email_exist'),
  231. 'password.required' => trans('auth.password_null'),
  232. 'password.min' => trans('auth.password_limit'),
  233. 'confirmPassword.required' => trans(
  234. 'auth.confirm_password'
  235. ),
  236. 'confirmPassword.same' => trans('auth.password_same'),
  237. 'term.accepted' => trans('auth.unaccepted'),
  238. ]
  239. );
  240. if ($validator->fails()) {
  241. return Redirect::back()->withInput()->withErrors(
  242. $validator->errors()
  243. );
  244. }
  245. $username = $request->input('username');
  246. $email = $request->input('email');
  247. $password = $request->input('password');
  248. $register_token = $request->input('register_token');
  249. $code = $request->input('code');
  250. $verify_code = $request->input('verify_code');
  251. $aff = (int)$request->input('aff');
  252. // 防止重复提交
  253. if ($register_token !== Session::get('register_token')) {
  254. return Redirect::back()->withInput()->withErrors(
  255. trans('auth.repeat_request')
  256. );
  257. }
  258. Session::forget('register_token');
  259. // 是否开启注册
  260. if ( ! sysConfig('is_register')) {
  261. return Redirect::back()->withErrors(
  262. trans('auth.register_close')
  263. );
  264. }
  265. // 校验域名邮箱黑白名单
  266. if (sysConfig('is_email_filtering')) {
  267. $result = $this->emailChecker($email, 1);
  268. if ($result !== false) {
  269. return $result;
  270. }
  271. }
  272. // 如果需要邀请注册
  273. if (sysConfig('is_invite_register')) {
  274. // 校验邀请码合法性
  275. if ($code) {
  276. if (Invite::whereCode($code)->whereStatus(0)->doesntExist(
  277. )) {
  278. return Redirect::back()
  279. ->withInput($request->except(['code']))
  280. ->withErrors(trans('auth.code_error'));
  281. }
  282. } elseif (sysConfig('is_invite_register') == 2) { // 必须使用邀请码
  283. return Redirect::back()->withInput()->withErrors(
  284. trans('auth.code_null')
  285. );
  286. }
  287. }
  288. // 注册前发送激活码
  289. if (sysConfig('is_activate_account') == 1) {
  290. if ( ! $verify_code) {
  291. return Redirect::back()
  292. ->withInput(
  293. $request->except(['verify_code'])
  294. )
  295. ->withErrors(trans('auth.captcha_null'));
  296. }
  297. $verifyCode = VerifyCode::whereAddress($email)->whereCode(
  298. $verify_code
  299. )->whereStatus(0)->first();
  300. if ( ! $verifyCode) {
  301. return Redirect::back()
  302. ->withInput(
  303. $request->except(['verify_code'])
  304. )
  305. ->withErrors(trans('auth.captcha_overtime'));
  306. }
  307. $verifyCode->status = 1;
  308. $verifyCode->save();
  309. }
  310. // 是否校验验证码
  311. $captcha = $this->check_captcha($request);
  312. if ($captcha != false) {
  313. return $captcha;
  314. }
  315. // 24小时内同IP注册限制
  316. if (sysConfig('register_ip_limit') && Cache::has($cacheKey)) {
  317. $registerTimes = Cache::get($cacheKey);
  318. if ($registerTimes >= sysConfig('register_ip_limit')) {
  319. return Redirect::back()
  320. ->withInput($request->except(['code']))
  321. ->withErrors(trans('auth.register_anti'));
  322. }
  323. }
  324. // 获取可用端口
  325. $port = Helpers::getPort();
  326. if ($port > sysConfig('max_port')) {
  327. return Redirect::back()->withInput()->withErrors(
  328. trans('auth.register_close')
  329. );
  330. }
  331. // 获取aff
  332. $affArr = $this->getAff($code, $aff);
  333. $inviter_id = $affArr['inviter_id'];
  334. $transfer_enable = MB * ((int)sysConfig(
  335. 'default_traffic'
  336. ) + ($inviter_id ? (int)sysConfig('referral_traffic') : 0));
  337. // 创建新用户
  338. $uid = Helpers::addUser(
  339. $email,
  340. Hash::make($password),
  341. $transfer_enable,
  342. sysConfig('default_days'),
  343. $inviter_id
  344. );
  345. // 注册失败,抛出异常
  346. if ( ! $uid) {
  347. return Redirect::back()->withInput()->withErrors(
  348. trans('auth.register_fail')
  349. );
  350. }
  351. // 更新昵称
  352. User::find($uid)->update(['username' => $username]);
  353. // 注册次数+1
  354. if (Cache::has($cacheKey)) {
  355. Cache::increment($cacheKey);
  356. } else {
  357. Cache::put($cacheKey, 1, Day); // 24小时
  358. }
  359. // 更新邀请码
  360. if ($affArr['code_id'] && sysConfig('is_invite_register')) {
  361. Invite::find($affArr['code_id'])->update(
  362. ['invitee_id' => $uid, 'status' => 1]
  363. );
  364. }
  365. // 清除邀请人Cookie
  366. Cookie::unqueue('register_aff');
  367. // 注册后发送激活码
  368. if (sysConfig('is_activate_account') == 2) {
  369. // 生成激活账号的地址
  370. $token = $this->addVerifyUrl($uid, $email);
  371. $activeUserUrl = sysConfig('website_url') . '/active/' . $token;
  372. $logId = Helpers::addNotificationLog(
  373. '注册激活',
  374. '请求地址:' . $activeUserUrl,
  375. 1,
  376. $email
  377. );
  378. Mail::to($email)->send(new activeUser($logId, $activeUserUrl));
  379. Session::flash(
  380. 'regSuccessMsg',
  381. trans('auth.register_active_tip')
  382. );
  383. } else {
  384. // 则直接给推荐人加流量
  385. if ($inviter_id) {
  386. $referralUser = User::find($inviter_id);
  387. if ($referralUser && $referralUser->expired_at >= date(
  388. 'Y-m-d'
  389. )) {
  390. (new UserService($referralUser))->incrementData(
  391. sysConfig('referral_traffic') * MB
  392. );
  393. }
  394. }
  395. if (sysConfig('is_activate_account') == 1) {
  396. User::find($uid)->update(['status' => 1]);
  397. }
  398. Session::flash('regSuccessMsg', trans('auth.register_success'));
  399. }
  400. return Redirect::to('login')->withInput();
  401. }
  402. $view['emailList'] = sysConfig(
  403. 'is_email_filtering'
  404. ) != 2 ? false : EmailFilter::whereType(2)->get();
  405. Session::put('register_token', Str::random());
  406. return view('auth.register', $view);
  407. }
  408. //邮箱检查
  409. private function emailChecker($email, $returnType = 0)
  410. {
  411. $emailFilterList = $this->emailFilterList(
  412. sysConfig('is_email_filtering')
  413. );
  414. $emailSuffix = explode('@', $email); // 提取邮箱后缀
  415. switch (sysConfig('is_email_filtering')) {
  416. // 黑名单
  417. case 1:
  418. if (in_array(
  419. strtolower($emailSuffix[1]),
  420. $emailFilterList,
  421. true
  422. )) {
  423. if ($returnType) {
  424. return Redirect::back()->withErrors(
  425. trans('auth.email_banned')
  426. );
  427. }
  428. return Response::json(
  429. [
  430. 'status' => 'fail',
  431. 'message' => trans('auth.email_banned'),
  432. ]
  433. );
  434. }
  435. break;
  436. //白名单
  437. case 2:
  438. if ( ! in_array(
  439. strtolower($emailSuffix[1]),
  440. $emailFilterList,
  441. true
  442. )) {
  443. if ($returnType) {
  444. return Redirect::back()->withErrors(
  445. trans('auth.email_invalid')
  446. );
  447. }
  448. return Response::json(
  449. [
  450. 'status' => 'fail',
  451. 'message' => trans('auth.email_invalid'),
  452. ]
  453. );
  454. }
  455. break;
  456. default:
  457. if ($returnType) {
  458. return Redirect::back()->withErrors(
  459. trans('auth.email_invalid')
  460. );
  461. }
  462. return Response::json(
  463. [
  464. 'status' => 'fail',
  465. 'message' => trans('auth.email_invalid'),
  466. ]
  467. );
  468. }
  469. return false;
  470. }
  471. /**
  472. * 获取AFF
  473. *
  474. * @param string|null $code 邀请码
  475. * @param int|null $aff URL中的aff参数
  476. *
  477. * @return array
  478. */
  479. private function getAff($code = null, $aff = null): array
  480. {
  481. $data = ['inviter_id' => null, 'code_id' => 0];// 邀请人ID 与 邀请码ID
  482. // 有邀请码先用邀请码,用谁的邀请码就给谁返利
  483. if ($code) {
  484. $inviteCode = Invite::whereCode($code)->whereStatus(0)->first();
  485. if ($inviteCode) {
  486. $data['inviter_id'] = $inviteCode->inviter_id;
  487. $data['code_id'] = $inviteCode->id;
  488. }
  489. }
  490. // 没有用邀请码或者邀请码是管理员生成的,则检查cookie或者url链接
  491. if ( ! $data['inviter_id']) {
  492. // 检查一下cookie里有没有aff
  493. $cookieAff = \Request::hasCookie('register_aff') ? \Request::cookie(
  494. 'register_aff'
  495. ) : 0;
  496. if ($cookieAff) {
  497. $data['inviter_id'] = User::find($cookieAff) ? $cookieAff : 0;
  498. } elseif ($aff) { // 如果cookie里没有aff,就再检查一下请求的url里有没有aff,因为有些人的浏览器会禁用了cookie,比如chrome开了隐私模式
  499. $data['inviter_id'] = User::find($aff) ? $aff : 0;
  500. }
  501. }
  502. return $data;
  503. }
  504. // 生成申请的请求地址
  505. private function addVerifyUrl($uid, $email)
  506. {
  507. $token = md5(
  508. sysConfig('website_name') . $email . microtime()
  509. );
  510. $verify = new Verify();
  511. $verify->type = 1;
  512. $verify->user_id = $uid;
  513. $verify->token = $token;
  514. $verify->status = 0;
  515. $verify->save();
  516. return $token;
  517. }
  518. // 重设密码页
  519. public function resetPassword(Request $request)
  520. {
  521. if ($request->isMethod('POST')) {
  522. // 校验请求
  523. $validator = Validator::make(
  524. $request->all(),
  525. [
  526. 'email' => 'required|email',
  527. ],
  528. [
  529. 'email.required' => trans('auth.email_null'),
  530. 'email.email' => trans('auth.email_legitimate'),
  531. ]
  532. );
  533. if ($validator->fails()) {
  534. return Redirect::back()->withInput()->withErrors(
  535. $validator->errors()
  536. );
  537. }
  538. $email = $request->input('email');
  539. // 是否开启重设密码
  540. if ( ! sysConfig('is_reset_password')) {
  541. return Redirect::back()->withErrors(
  542. trans(
  543. 'auth.reset_password_close',
  544. ['email' => sysConfig('webmaster_email')]
  545. )
  546. );
  547. }
  548. // 查找账号
  549. $user = User::whereEmail($email)->first();
  550. if ( ! $user) {
  551. return Redirect::back()->withErrors(
  552. trans('auth.email_notExist')
  553. );
  554. }
  555. // 24小时内重设密码次数限制
  556. $resetTimes = 0;
  557. if (Cache::has('resetPassword_' . md5($email))) {
  558. $resetTimes = Cache::get('resetPassword_' . md5($email));
  559. if ($resetTimes >= sysConfig('reset_password_times')) {
  560. return Redirect::back()->withErrors(
  561. trans(
  562. 'auth.reset_password_limit',
  563. ['time' => sysConfig('reset_password_times')]
  564. )
  565. );
  566. }
  567. }
  568. // 生成取回密码的地址
  569. $token = $this->addVerifyUrl($user->id, $email);
  570. // 发送邮件
  571. $resetPasswordUrl = sysConfig('website_url') . '/reset/' . $token;
  572. $logId = Helpers::addNotificationLog(
  573. '重置密码',
  574. '请求地址:' . $resetPasswordUrl,
  575. 1,
  576. $email
  577. );
  578. Mail::to($email)->send(
  579. new resetPassword($logId, $resetPasswordUrl)
  580. );
  581. Cache::put('resetPassword_' . md5($email), $resetTimes + 1, Day);
  582. return Redirect::back()->with(
  583. 'successMsg',
  584. trans(
  585. 'auth.reset_password_success_tip'
  586. )
  587. );
  588. }
  589. return view('auth.resetPassword');
  590. }
  591. // 重设密码
  592. public function reset(Request $request, $token)
  593. {
  594. if ( ! $token) {
  595. return Redirect::to('login');
  596. }
  597. if ($request->isMethod('POST')) {
  598. $validator = Validator::make(
  599. $request->all(),
  600. [
  601. 'password' => 'required|min:6',
  602. 'confirmPassword' => 'required|same:password',
  603. ],
  604. [
  605. 'password.required' => trans('auth.password_null'),
  606. 'password.min' => trans('auth.password_limit'),
  607. 'confirmPassword.required' => trans('auth.password_null'),
  608. 'confirmPassword.min' => trans('auth.password_limit'),
  609. 'confirmPassword.same' => trans('auth.password_same'),
  610. ]
  611. );
  612. if ($validator->fails()) {
  613. return Redirect::back()->withInput()->withErrors(
  614. $validator->errors()
  615. );
  616. }
  617. $password = $request->input('password');
  618. // 校验账号
  619. $verify = Verify::type(1)->whereToken($token)->first();
  620. $user = $verify->user;
  621. if ( ! $verify) {
  622. return Redirect::to('login');
  623. }
  624. if ($verify->status == 1) {
  625. return Redirect::back()->withErrors(trans('auth.overtime'));
  626. }
  627. if ($user->status < 0) {
  628. return Redirect::back()->withErrors(trans('auth.email_banned'));
  629. }
  630. if (Hash::check($password, $verify->user->password)) {
  631. return Redirect::back()->withErrors(
  632. trans('auth.reset_password_same_fail')
  633. );
  634. }
  635. // 更新密码
  636. if ( ! $user->update(['password' => Hash::make($password)])) {
  637. return Redirect::back()->withErrors(
  638. trans('auth.reset_password_fail')
  639. );
  640. }
  641. // 置为已使用
  642. $verify->status = 1;
  643. $verify->save();
  644. return Redirect::to('login')->with(
  645. 'successMsg',
  646. trans('auth.reset_password_new')
  647. );
  648. }
  649. $verify = Verify::type(1)->whereToken($token)->first();
  650. if ( ! $verify) {
  651. return Redirect::to('login');
  652. }
  653. if (time() - strtotime($verify->created_at) >= 1800) {
  654. // 置为已失效
  655. $verify->status = 2;
  656. $verify->save();
  657. }
  658. // 重新获取一遍verify
  659. $view['verify'] = Verify::type(1)->whereToken($token)->first();
  660. return view('auth.reset', $view);
  661. }
  662. // 激活账号页
  663. public function activeUser(Request $request)
  664. {
  665. if ($request->isMethod('POST')) {
  666. $validator = Validator::make(
  667. $request->all(),
  668. [
  669. 'email' => 'required|email|exists:user,email',
  670. ],
  671. [
  672. 'email.required' => trans('auth.email_null'),
  673. 'email.email' => trans('auth.email_legitimate'),
  674. 'email.exists' => trans('auth.email_notExist'),
  675. ]
  676. );
  677. if ($validator->fails()) {
  678. return Redirect::back()->withInput()->withErrors(
  679. $validator->errors()
  680. );
  681. }
  682. $email = $request->input('email');
  683. // 是否开启账号激活
  684. if (sysConfig('is_activate_account') != 2) {
  685. return Redirect::back()->withInput()->withErrors(
  686. trans(
  687. 'auth.active_close',
  688. ['email' => sysConfig('webmaster_email')]
  689. )
  690. );
  691. }
  692. // 查找账号
  693. $user = User::whereEmail($email)->firstOrFail();
  694. if ($user->status < 0) {
  695. return Redirect::back()->withErrors(
  696. trans(
  697. 'auth.login_ban',
  698. ['email' => sysConfig('webmaster_email')]
  699. )
  700. );
  701. }
  702. if ($user->status > 0) {
  703. return Redirect::back()->withErrors(trans('auth.email_normal'));
  704. }
  705. // 24小时内激活次数限制
  706. $activeTimes = 0;
  707. if (Cache::has('activeUser_' . md5($email))) {
  708. $activeTimes = Cache::get('activeUser_' . md5($email));
  709. if ($activeTimes >= sysConfig('active_times')) {
  710. return Redirect::back()->withErrors(
  711. trans(
  712. 'auth.active_limit',
  713. ['time' => sysConfig('webmaster_email')]
  714. )
  715. );
  716. }
  717. }
  718. // 生成激活账号的地址
  719. $token = $this->addVerifyUrl($user->id, $email);
  720. // 发送邮件
  721. $activeUserUrl = sysConfig('website_url') . '/active/' . $token;
  722. $logId = Helpers::addNotificationLog(
  723. '激活账号',
  724. '请求地址:' . $activeUserUrl,
  725. 1,
  726. $email
  727. );
  728. Mail::to($email)->send(new activeUser($logId, $activeUserUrl));
  729. Cache::put('activeUser_' . md5($email), $activeTimes + 1, Day);
  730. return Redirect::back()->with(
  731. 'successMsg',
  732. trans('auth.register_active_tip')
  733. );
  734. }
  735. return view('auth.activeUser');
  736. }
  737. // 激活账号
  738. public function active($token)
  739. {
  740. if ( ! $token) {
  741. return Redirect::to('login');
  742. }
  743. $verify = Verify::type(1)->with('user')->whereToken($token)->first();
  744. $user = $verify->user;
  745. if ( ! $verify) {
  746. return Redirect::to('login');
  747. }
  748. if (empty($user)) {
  749. Session::flash('errorMsg', trans('auth.overtime'));
  750. return view('auth.active');
  751. }
  752. if ($verify->status > 0) {
  753. Session::flash('errorMsg', trans('auth.overtime'));
  754. return view('auth.active');
  755. }
  756. if ($user->status != 0) {
  757. Session::flash('errorMsg', trans('auth.email_normal'));
  758. return view('auth.active');
  759. }
  760. if (time() - strtotime($verify->created_at) >= 1800) {
  761. Session::flash('errorMsg', trans('auth.overtime'));
  762. // 置为已失效
  763. $verify->status = 2;
  764. $verify->save();
  765. return view('auth.active');
  766. }
  767. // 更新账号状态
  768. if ( ! $user->update(['status' => 1])) {
  769. Session::flash('errorMsg', trans('auth.active_fail'));
  770. return Redirect::back();
  771. }
  772. // 置为已使用
  773. $verify->status = 1;
  774. $verify->save();
  775. // 账号激活后给邀请人送流量
  776. $inviter = $user->inviter;
  777. if ($inviter) {
  778. (new UserService($inviter))->incrementData(
  779. sysConfig('referral_traffic') * MB
  780. );
  781. }
  782. Session::flash('successMsg', trans('auth.active_success'));
  783. return view('auth.active');
  784. }
  785. // 发送注册验证码
  786. public function sendCode(Request $request)
  787. {
  788. $validator = Validator::make(
  789. $request->all(),
  790. [
  791. 'email' => 'required|email|unique:user',
  792. ],
  793. [
  794. 'email.required' => trans('auth.email_null'),
  795. 'email.email' => trans('auth.email_legitimate'),
  796. 'email.unique' => trans('auth.email_exist'),
  797. ]
  798. );
  799. $email = $request->input('email');
  800. if ($validator->fails()) {
  801. return Response::json(
  802. [
  803. 'status' => 'fail',
  804. 'message' => $validator->getMessageBag()->first(),
  805. ]
  806. );
  807. }
  808. $ip = IP::getClientIP();
  809. // 校验域名邮箱黑白名单
  810. if (sysConfig('is_email_filtering')) {
  811. $result = $this->emailChecker($email);
  812. if ($result !== false) {
  813. return $result;
  814. }
  815. }
  816. // 是否开启注册发送验证码
  817. if (sysConfig('is_activate_account') != 1) {
  818. return Response::json(
  819. ['status' => 'fail', 'message' => trans('auth.captcha_close')]
  820. );
  821. }
  822. // 防刷机制
  823. if (Cache::has('send_verify_code_' . md5($ip))) {
  824. return Response::json(
  825. ['status' => 'fail', 'message' => trans('auth.register_anti')]
  826. );
  827. }
  828. // 发送邮件
  829. $code = Str::random(6);
  830. $logId = Helpers::addNotificationLog(
  831. '发送注册验证码',
  832. '验证码:' . $code,
  833. 1,
  834. $email
  835. );
  836. Mail::to($email)->send(new sendVerifyCode($logId, $code));
  837. $this->addVerifyCode($email, $code);
  838. Cache::put('send_verify_code_' . md5($ip), $ip, Minute);
  839. return Response::json(
  840. ['status' => 'success', 'message' => trans('auth.captcha_send')]
  841. );
  842. }
  843. // 生成注册验证码
  844. private function addVerifyCode($email, $code): void
  845. {
  846. $verify = new VerifyCode();
  847. $verify->address = $email;
  848. $verify->code = $code;
  849. $verify->status = 0;
  850. $verify->save();
  851. }
  852. // 公开的邀请码列表
  853. public function free()
  854. {
  855. $view['inviteList'] = Invite::whereInviterId(0)
  856. ->whereStatus(0)
  857. ->paginate();
  858. return view('auth.free', $view);
  859. }
  860. // 切换语言
  861. public function switchLang($locale): RedirectResponse
  862. {
  863. Session::put("locale", $locale);
  864. return Redirect::back();
  865. }
  866. }