fix: API 인증 에러 처리 개선 및 요청 로그 강화

- Handler.php: API 라우트는 Accept 헤더 없어도 JSON 응답 반환
- ApiKeyMiddleware: 요청 로그에 헤더 정보 추가 (X-API-KEY, Authorization 마스킹)
- Route [login] not defined 에러 해결
- 인증 실패 시 401 JSON 응답으로 일관성 확보
This commit is contained in:
2025-11-25 09:14:33 +09:00
parent 757c5d901c
commit 3fefb8ce26
3 changed files with 49 additions and 1 deletions

View File

@@ -1,5 +1,45 @@
# SAM API 작업 현황
## 2025-11-25 (월) - API 인증 에러 처리 개선 및 요청 로그 강화
### 문제 상황
- GET /item-master/init 요청 시 `Route [login] not defined` 에러 발생
- user_id null (인증 실패 상태)
- API Request 로그에 헤더 정보 누락
### 근본 원인
1. **Handler.php**: `expectsJson()` 체크만 있어서, Accept 헤더 없는 API 요청이 기본 동작(로그인 리다이렉트)으로 처리됨
2. **ApiKeyMiddleware**: 요청 로그에 헤더 정보 (X-API-KEY, Authorization) 미포함
### 해결 방안
**Handler.php (app/Exceptions/Handler.php)**
- Line 60: API 라우트 체크 추가 (`str_starts_with($request->path(), 'api/')`)
- Line 62: `$request->expectsJson() || $isApiRoute` 조건으로 변경
- 효과: Accept 헤더 없어도 API 라우트는 무조건 JSON 응답 반환
**ApiKeyMiddleware (app/Http/Middleware/ApiKeyMiddleware.php)**
- Line 52-57: headers 필드 추가
- X-API-KEY: 마스킹 ('***')
- Authorization: Bearer 토큰 마스킹 ('Bearer ***')
- Accept, Content-Type: 원본 그대로
- 효과: 인증 문제 디버깅 용이
### 수정된 파일
- `app/Exceptions/Handler.php`
- `app/Http/Middleware/ApiKeyMiddleware.php`
### 검증 결과
- PHP 문법 체크: ✅ 통과
- Pint 코드 포맷팅: ✅ 통과
### 기대 효과
1. API 요청 시 Accept 헤더 없어도 정상 JSON 응답
2. 인증 실패 시 로그인 리다이렉트 대신 401 JSON 응답
3. 요청 로그에서 헤더 정보 확인 가능 (디버깅 개선)
---
## 2025-11-24 (일) - 소프트삭제 및 타임스탬프 감사 컬럼 추가
### 작업 목표

View File

@@ -56,8 +56,10 @@ protected function sendSlackException(Throwable $e): void
public function render($request, Throwable $exception)
{
// API 라우트는 무조건 JSON 응답 (Accept 헤더 없어도)
$isApiRoute = str_starts_with($request->path(), 'api/');
if ($request->expectsJson()) {
if ($request->expectsJson() || $isApiRoute) {
// 422 Unprocessable Entity - Validation 실패
if ($exception instanceof ValidationException) {
return response()->json([

View File

@@ -49,6 +49,12 @@ public function handle(Request $request, Closure $next)
'uri' => $request->getRequestUri(),
'input' => $request->except(['password', 'password_confirmation']), // 민감 정보 제외
'user_agent' => $request->userAgent(),
'headers' => [
'X-API-KEY' => $request->header('X-API-KEY') ? '***' : null,
'Authorization' => $request->bearerToken() ? 'Bearer ***' : null,
'Accept' => $request->header('Accept'),
'Content-Type' => $request->header('Content-Type'),
],
]);
}