validated(); $username = $credentials['username']; $password = $credentials['password']; $ip = $request->ip(); $user = User::where('username', $username)->first(); if ($user) { // 用户存在,验证密码 if (Hash::check($password, $user->password)) { // Bcrypt 验证通过 // 检测是否被封禁 (后台管理员级别获得豁免权,防止误把自己关在门外) $adminLevel = (int) Sysparam::getValue('superlevel', '100'); if ($user->user_level < $adminLevel) { if ($user->user_level < 0) { return response()->json(['status' => 'error', 'message' => '您的账号已被管理员封禁,无法登录。'], 403); } if (Redis::sismember('banned_ips', $ip)) { return response()->json(['status' => 'error', 'message' => '您所在的 IP 地址已被管理员封禁,限制访问。'], 403); } } $this->performLogin($user, $ip); return response()->json(['status' => 'success', 'message' => '登录成功']); } // 退化为 MD5 验证(兼容原 ASP 系统的老密码) if (md5($password) === $user->password) { // MD5 验证通过,升级密码为 Bcrypt $user->password = Hash::make($password); $user->save(); // 检测是否被封禁 (后台管理员级别获得豁免权,防止误把自己关在门外) $adminLevel = (int) Sysparam::getValue('superlevel', '100'); if ($user->user_level < $adminLevel) { if ($user->user_level < 0) { return response()->json(['status' => 'error', 'message' => '您的账号已被管理员封禁,无法登录。'], 403); } if (Redis::sismember('banned_ips', $ip)) { return response()->json(['status' => 'error', 'message' => '您所在的 IP 地址已被管理员封禁,限制访问。'], 403); } } $this->performLogin($user, $ip); return response()->json(['status' => 'success', 'message' => '登录成功,且安全策略已自动升级']); } // 密码错误 return response()->json([ 'status' => 'error', 'message' => '密码错误,请重试。', ], 422); } // --- 核心:第一次登录即为注册 --- // 映射性别:1=男 2=女 0=保密(数据库 sex 列为 int) $sex = (int) $request->input('bSex', 0); if (! in_array($sex, [1, 2])) { $sex = 0; } // 新注册用户:只检测 IP 封禁 (新号不存在账号封禁) if (Redis::sismember('banned_ips', $ip)) { return response()->json(['status' => 'error', 'message' => '您所在的 IP 地址已被管理员封禁,禁止注册新账号。'], 403); } // 检测用户名是否在禁用词列表(永久禁用 或 改名临时保留期内) if (UsernameBlacklist::isBlocked($username)) { return response()->json(['status' => 'error', 'message' => '该用户名已被系统禁止注册,请更换其他名称。'], 422); } // --- 提取邀请人 Cookie --- $inviterIdCookie = $request->cookie('inviter_id'); $inviterId = null; if ($inviterIdCookie && is_numeric($inviterIdCookie)) { // 简单校验邀请人是否存在,防止脏数据 if (User::where('id', $inviterIdCookie)->exists()) { $inviterId = (int) $inviterIdCookie; } } $newUser = User::create([ 'username' => $username, 'password' => Hash::make($password), 'first_ip' => $ip, 'last_ip' => $ip, 'user_level' => 1, // 默认普通用户等级 'sex' => $sex, 'usersf' => '1.gif', // 默认头像 'inviter_id' => $inviterId, // 记录邀请人 ]); $this->performLogin($newUser, $ip); // 如果是通过邀请注册的,响应成功后建议清除 Cookie,防止污染后续注册 if ($inviterId) { \Illuminate\Support\Facades\Cookie::queue(\Illuminate\Support\Facades\Cookie::forget('inviter_id')); } return response()->json(['status' => 'success', 'message' => '注册并登录成功!']); } /** * 执行实际的登录操作并记录时间、IP 等。 */ private function performLogin(User $user, string $ip): void { Auth::login($user); // 递增访问次数 $user->increment('visit_num'); // 更新最后登录IP和时间(同时将旧IP转移到 previous_ip 作上次登录记录) $user->update([ 'previous_ip' => $user->last_ip, 'last_ip' => $ip, 'log_time' => now(), 'in_time' => now(), ]); // 可选:将用户登录状态也同步写入原有的 IpLog 模型,以便数据归档查询 \App\Models\IpLog::create([ 'ip' => $ip, 'sdate' => now(), 'uuname' => $user->username, ]); // 触发微信机器人消息推送 (登录上线类) try { $wechatService = new \App\Services\WechatBot\WechatNotificationService; $wechatService->notifyAdminOnline($user); $wechatService->notifyFriendsOnline($user); $wechatService->notifySpouseOnline($user); } catch (\Exception $e) { \Illuminate\Support\Facades\Log::error('WechatBot presence notification failed', ['error' => $e->getMessage()]); } } /** * 退出登录,清除会话后跳转回登录首页 */ public function logout(Request $request): \Illuminate\Http\RedirectResponse { if (Auth::check()) { $user = Auth::user(); // 记录退出时间和退出信息 $user->update([ 'out_time' => now(), 'out_info' => '正常退出了聊天室', ]); } Auth::logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); return redirect('/')->with('success', '您已成功退出聊天室,欢迎下次再来!'); } }