Files
Gnuboard7/app/Http/Middleware/MaintenanceModePage.php
T
HeuJung 062a88ca04 feat(core): DB 최고권한 계정 차단 + OPcache 상태 안내
설치 단계와 코어 부팅의 정책이 엇갈려 있었다. 인스톨러는 root 를 자유롭게
허용하면서, 설치 후 부팅은 같은 값을 보고 확장 로딩 전체를 조용히 스킵했다.
설치는 성공하지만 이후 깨진 화면만 뜨고 원인은 로그 한 줄에만 남았다.

판정을 프레임워크 의존성 0 인 공용 SSoT 로 모아 인스톨러와 코어가 같은 답을
내게 하고, 설치 단계에서 서버 2경로로 차단하며, 설치 후 변경은 전용 에러
페이지로 드러낸다. 가드를 boot 가 아닌 미들웨어에 두어 artisan 이 죽지 않게
해 복구 수단을 남겼다. admin 은 일반 권한 운영 계정 오차단을 막기 위해 차단
목록에서 제외했다.

OPcache 는 상태 조회 경로 자체가 없어 성능 저하를 인지할 방법이 없었다.
설치 단계 경고(비차단)와 관리자 정보 탭 표시를 같은 판정 SSoT 로 추가했다.
확장 로드 여부만으로는 부족해 opcache.enable 지시자까지 확인하며, ini_get 이
차단된 환경은 "확인 불가"로 폴백해 경고도 차단도 하지 않는다.
2026-07-20 14:17:49 +09:00

83 lines
2.5 KiB
PHP

<?php
namespace App\Http\Middleware;
use App\Http\Middleware\Concerns\DetectsRequestLocale;
use Closure;
use Illuminate\Foundation\Http\MaintenanceModeBypassCookie;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class MaintenanceModePage
{
use DetectsRequestLocale;
/**
* Maintenance 모드일 때 전용 정적 페이지를 렌더링합니다.
*
* DB, API, JS 에셋에 의존하지 않는 자체 완결 Blade 페이지를 반환합니다.
* 메인터넌스 모드는 시스템 불안정 시(DB 마이그레이션, 코어 업데이트 등) 사용되므로
* 외부 의존성 없이 동작해야 합니다.
*
* @param Request $request HTTP 요청
* @param Closure $next 다음 미들웨어
* @return Response HTTP 응답
*/
public function handle(Request $request, Closure $next): Response
{
if (! app()->isDownForMaintenance()) {
return $next($request);
}
// secret 쿠키가 있으면 통과 (관리자 접근)
if ($this->hasValidBypassCookie($request)) {
return $next($request);
}
// 로케일 감지 (SetLocale 미들웨어가 실행되지 않으므로 자체 감지)
// API/HTML 분기보다 먼저 적용해야 JSON 응답 메시지도 ja 등 활성 언어팩 로케일을 반영한다
$locale = $this->detectLocale($request);
app()->setLocale($locale);
// API 요청은 JSON 응답
if ($request->expectsJson() || $request->is('api/*')) {
return response()->json([
'success' => false,
'message' => __('maintenance.message'),
], 503);
}
// 정적 메인터넌스 페이지 렌더링 (DB/API/JS 무의존)
return response()->view('maintenance', [], 503);
}
/**
* 유효한 bypass 쿠키가 있는지 확인합니다.
*
* @param Request $request HTTP 요청
* @return bool
*/
protected function hasValidBypassCookie(Request $request): bool
{
$downFilePath = storage_path('framework/down');
if (! file_exists($downFilePath)) {
return false;
}
$data = json_decode(file_get_contents($downFilePath), true);
if (! isset($data['secret'])) {
return false;
}
$cookie = $request->cookie('laravel_maintenance');
if (! $cookie) {
return false;
}
return MaintenanceModeBypassCookie::isValid($cookie, $data['secret']);
}
}