configureSecureUrls(); // 注册登录入口限流器,阻断爆破和批量注册滥用。 $this->registerAuthRateLimiters(); // 注册婚姻系统消息订阅者(结婚/婚礼/离婚通知写入聊天历史) Event::subscribe(SaveMarriageSystemMessage::class); // 动态加载自定义 SMTP 配置 (如果有数据库则执行) try { if (Schema::hasTable('sysparam')) { $smtpConfig = Sysparam::where('alias', 'like', 'smtp_%')->pluck('body', 'alias'); if ($smtpConfig->isNotEmpty() && $smtpConfig->get('smtp_host')) { Config::set('mail.default', 'smtp'); Config::set('mail.mailers.smtp', [ 'transport' => 'smtp', 'host' => $smtpConfig->get('smtp_host'), 'port' => $smtpConfig->get('smtp_port', 465), 'encryption' => $smtpConfig->get('smtp_encryption', 'ssl'), 'username' => $smtpConfig->get('smtp_username'), 'password' => $smtpConfig->get('smtp_password'), 'timeout' => 10, 'local_domain' => env('MAIL_EHLO_DOMAIN'), ]); Config::set('mail.from', [ 'address' => $smtpConfig->get('smtp_from_address', $smtpConfig->get('smtp_username')), 'name' => $smtpConfig->get('smtp_from_name', '飘落流星聊天室'), ]); } } } catch (\Exception $e) { // 在安装初期表不存在时忽略,防止应用崩溃 } } /** * 根据应用配置决定是否统一强制 HTTPS 方案。 */ private function configureSecureUrls(): void { if (! config('app.force_https')) { return; } URL::forceScheme('https'); } /** * 注册聊天室前台登录与隐藏后台登录的独立限流器。 */ private function registerAuthRateLimiters(): void { RateLimiter::for('chat-login', function (Request $request): Limit { return Limit::perMinute(5) ->by($this->buildAuthRateLimitKey($request, 'chat-login')) ->response(function (Request $request, array $headers) { return response()->json([ 'status' => 'error', 'message' => '登录尝试过于频繁,请 1 分钟后再试。', ], 429, $headers); }); }); RateLimiter::for('admin-hidden-login', function (Request $request): Limit { return Limit::perMinute(5) ->by($this->buildAuthRateLimitKey($request, 'admin-hidden-login')) ->response(function (Request $request, array $headers) { $response = redirect()->route('admin.login') ->withInput($request->except(['password', 'captcha'])) ->withErrors(['username' => '登录尝试过于频繁,请 1 分钟后再试。']); foreach ($headers as $headerName => $headerValue) { $response->headers->set($headerName, $headerValue); } $response->setStatusCode(429); return $response; }); }); } /** * 构造登录限流键,按场景 + 用户名 + IP 维度隔离计数。 */ private function buildAuthRateLimitKey(Request $request, string $scene): string { $username = Str::lower(trim((string) $request->input('username', 'guest'))); return implode('|', [$scene, $username, $request->ip()]); } }