fix: API 인증 에러 처리 개선 및 요청 로그 강화
- Handler.php: API 라우트는 Accept 헤더 없어도 JSON 응답 반환 - ApiKeyMiddleware: 요청 로그에 헤더 정보 추가 (X-API-KEY, Authorization 마스킹) - Route [login] not defined 에러 해결 - 인증 실패 시 401 JSON 응답으로 일관성 확보
This commit is contained in:
@@ -1,5 +1,45 @@
|
|||||||
# SAM API 작업 현황
|
# 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 (일) - 소프트삭제 및 타임스탬프 감사 컬럼 추가
|
## 2025-11-24 (일) - 소프트삭제 및 타임스탬프 감사 컬럼 추가
|
||||||
|
|
||||||
### 작업 목표
|
### 작업 목표
|
||||||
|
|||||||
@@ -56,8 +56,10 @@ protected function sendSlackException(Throwable $e): void
|
|||||||
|
|
||||||
public function render($request, Throwable $exception)
|
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 실패
|
// 422 Unprocessable Entity - Validation 실패
|
||||||
if ($exception instanceof ValidationException) {
|
if ($exception instanceof ValidationException) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
|
|||||||
@@ -49,6 +49,12 @@ public function handle(Request $request, Closure $next)
|
|||||||
'uri' => $request->getRequestUri(),
|
'uri' => $request->getRequestUri(),
|
||||||
'input' => $request->except(['password', 'password_confirmation']), // 민감 정보 제외
|
'input' => $request->except(['password', 'password_confirmation']), // 민감 정보 제외
|
||||||
'user_agent' => $request->userAgent(),
|
'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'),
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user