148 lines
4.7 KiB
PHP
148 lines
4.7 KiB
PHP
<?php
|
|
|
|
/**
|
|
* 文件功能:后台隐藏登录控制器
|
|
*
|
|
* 仅提供站长独立登录入口,登录成功后直接进入后台控制台,
|
|
* 不经过聊天室首页与“登录即注册”流程。
|
|
*
|
|
* @author ChatRoom Laravel
|
|
*
|
|
* @version 1.0.0
|
|
*/
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\AdminLoginRequest;
|
|
use App\Models\User;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\View\View;
|
|
|
|
/**
|
|
* 类功能:处理站长隐藏登录页展示与登录提交。
|
|
*/
|
|
class AdminAuthController extends Controller
|
|
{
|
|
/**
|
|
* 隐藏登录入口后缀。
|
|
*/
|
|
private const LOGIN_SUFFIX = 'lkddi';
|
|
|
|
/**
|
|
* 站长账号固定主键。
|
|
*/
|
|
private const SITE_OWNER_ID = 1;
|
|
|
|
/**
|
|
* 显示站长隐藏登录页面。
|
|
*/
|
|
public function create(Request $request): View|RedirectResponse
|
|
{
|
|
// 已通过隐藏入口登录的站长再次访问时,直接回后台首页
|
|
if (Auth::id() === self::SITE_OWNER_ID && $request->session()->get('admin_login_via_hidden')) {
|
|
return redirect()->route('admin.dashboard');
|
|
}
|
|
|
|
return view('admin.auth.login', [
|
|
'loginSuffix' => self::LOGIN_SUFFIX,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 处理站长隐藏登录请求。
|
|
*/
|
|
public function store(AdminLoginRequest $request): RedirectResponse
|
|
{
|
|
$validated = $request->validated();
|
|
$siteOwner = User::query()->find(self::SITE_OWNER_ID);
|
|
|
|
// 只有 id=1 的站长账号允许通过该入口进入后台
|
|
if (! $siteOwner || $siteOwner->username !== $validated['username']) {
|
|
return back()
|
|
->withInput($request->safe()->only(['username']))
|
|
->withErrors(['username' => '该入口仅限站长账号使用。']);
|
|
}
|
|
|
|
if (! $this->passwordMatches($siteOwner, $validated['password'])) {
|
|
return back()
|
|
->withInput($request->safe()->only(['username']))
|
|
->withErrors(['password' => '账号或密码错误。']);
|
|
}
|
|
|
|
// 若当前已有其他账号占用会话,先退出后再切换为站长会话
|
|
if (Auth::check() && Auth::id() !== $siteOwner->id) {
|
|
Auth::logout();
|
|
}
|
|
|
|
Auth::login($siteOwner);
|
|
$request->session()->regenerate();
|
|
$request->session()->put('admin_login_via_hidden', true);
|
|
|
|
// 复用主登录的会话登记逻辑,保证后台入口也会更新登录痕迹
|
|
$this->recordAdminLogin($siteOwner, (string) $request->ip());
|
|
|
|
return redirect()->route('admin.dashboard')->with('success', '站长后台登录成功。');
|
|
}
|
|
|
|
/**
|
|
* 校验站长密码,兼容旧库 MD5 并自动升级为 bcrypt。
|
|
*/
|
|
private function passwordMatches(User $siteOwner, string $plainPassword): bool
|
|
{
|
|
try {
|
|
if (Hash::check($plainPassword, $siteOwner->password)) {
|
|
return true;
|
|
}
|
|
} catch (\RuntimeException $exception) {
|
|
// 旧库非 bcrypt 密码会在这里抛异常,后续继续走 MD5 兼容逻辑
|
|
}
|
|
|
|
if (md5($plainPassword) !== $siteOwner->password) {
|
|
return false;
|
|
}
|
|
|
|
// 兼容老密码登录成功后,立即升级为 Laravel 默认哈希
|
|
$siteOwner->forceFill([
|
|
'password' => Hash::make($plainPassword),
|
|
])->save();
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 记录站长通过隐藏入口登录后的访问痕迹。
|
|
*/
|
|
private function recordAdminLogin(User $siteOwner, string $ip): void
|
|
{
|
|
// 登录成功后补齐访问次数、IP 与时间,保持与前台登录统计一致
|
|
$siteOwner->increment('visit_num');
|
|
$siteOwner->update([
|
|
'previous_ip' => $siteOwner->last_ip,
|
|
'last_ip' => $ip,
|
|
'log_time' => now(),
|
|
'in_time' => now(),
|
|
]);
|
|
|
|
\App\Models\IpLog::create([
|
|
'ip' => $ip,
|
|
'sdate' => now(),
|
|
'uuname' => $siteOwner->username,
|
|
]);
|
|
|
|
try {
|
|
$wechatService = new \App\Services\WechatBot\WechatNotificationService;
|
|
$wechatService->notifyAdminOnline($siteOwner);
|
|
$wechatService->notifyFriendsOnline($siteOwner);
|
|
$wechatService->notifySpouseOnline($siteOwner);
|
|
} catch (\Exception $exception) {
|
|
// 机器人通知异常不影响站长进入后台,但需要落日志便于排查
|
|
Log::error('Hidden admin login notification failed', ['error' => $exception->getMessage()]);
|
|
}
|
|
}
|
|
}
|