diff --git a/PHASE3.14_AUTH_SERVICE_MIGRATION.md b/PHASE3.14_AUTH_SERVICE_MIGRATION.md index 4180b1d6..26920260 100644 --- a/PHASE3.14_AUTH_SERVICE_MIGRATION.md +++ b/PHASE3.14_AUTH_SERVICE_MIGRATION.md @@ -9,12 +9,12 @@ AuthService는 **5개의 Prisma 호출**이 있으며, 사용자 인증 및 권 | 항목 | 내용 | | --------------- | ------------------------------------------ | | 파일 위치 | `backend-node/src/services/authService.ts` | -| 파일 크기 | 334 라인 | -| Prisma 호출 | 5개 | -| **현재 진행률** | **0/5 (0%)** 🔄 **진행 예정** | +| 파일 크기 | 335 라인 | +| Prisma 호출 | 0개 (이미 Phase 1.5에서 전환 완료) | +| **현재 진행률** | **5/5 (100%)** ✅ **전환 완료** | | 복잡도 | 높음 (보안, 암호화, 세션 관리) | | 우선순위 | 🟡 중간 (Phase 3.14) | -| **상태** | ⏳ **대기 중** | +| **상태** | ✅ **완료** (Phase 1.5에서 이미 완료) | ### 🎯 전환 목표 @@ -33,26 +33,31 @@ AuthService는 **5개의 Prisma 호출**이 있으며, 사용자 인증 및 권 ### 주요 기능 (5개 예상) #### 1. **사용자 로그인 (인증)** + - findFirst or findUnique - 이메일/사용자명으로 조회 - 비밀번호 검증 #### 2. **사용자 정보 조회** + - findUnique - user_id 기준 - 권한 정보 포함 #### 3. **사용자 생성 (회원가입)** + - create - 비밀번호 암호화 - 중복 검사 #### 4. **비밀번호 변경** + - update - 기존 비밀번호 검증 - 새 비밀번호 암호화 #### 5. **세션 관리** + - create, update, delete - 세션 토큰 저장/조회 @@ -61,14 +66,17 @@ AuthService는 **5개의 Prisma 호출**이 있으며, 사용자 인증 및 권 ## 💡 전환 전략 ### 1단계: 인증 관련 전환 (2개) + - login() - 사용자 조회 + 비밀번호 검증 - getUserInfo() - 사용자 정보 조회 ### 2단계: 사용자 관리 전환 (2개) + - createUser() - 사용자 생성 - changePassword() - 비밀번호 변경 ### 3단계: 세션 관리 전환 (1개) + - manageSession() - 세션 CRUD --- @@ -78,6 +86,7 @@ AuthService는 **5개의 Prisma 호출**이 있으며, 사용자 인증 및 권 ### 예시 1: 로그인 (비밀번호 검증) **변경 전**: + ```typescript async login(username: string, password: string) { const user = await prisma.users.findFirst({ @@ -95,7 +104,7 @@ async login(username: string, password: string) { } const isPasswordValid = await bcrypt.compare(password, user.password_hash); - + if (!isPasswordValid) { throw new Error("Invalid password"); } @@ -105,11 +114,12 @@ async login(username: string, password: string) { ``` **변경 후**: + ```typescript async login(username: string, password: string) { const user = await queryOne( - `SELECT * FROM users - WHERE (username = $1 OR email = $1) + `SELECT * FROM users + WHERE (username = $1 OR email = $1) AND is_active = $2`, [username, true] ); @@ -119,7 +129,7 @@ async login(username: string, password: string) { } const isPasswordValid = await bcrypt.compare(password, user.password_hash); - + if (!isPasswordValid) { throw new Error("Invalid password"); } @@ -131,6 +141,7 @@ async login(username: string, password: string) { ### 예시 2: 사용자 생성 (비밀번호 암호화) **변경 전**: + ```typescript async createUser(userData: CreateUserDto) { // 중복 검사 @@ -165,11 +176,12 @@ async createUser(userData: CreateUserDto) { ``` **변경 후**: + ```typescript async createUser(userData: CreateUserDto) { // 중복 검사 const existing = await queryOne( - `SELECT * FROM users + `SELECT * FROM users WHERE username = $1 OR email = $2`, [userData.username, userData.email] ); @@ -183,7 +195,7 @@ async createUser(userData: CreateUserDto) { // 사용자 생성 const user = await queryOne( - `INSERT INTO users + `INSERT INTO users (username, email, password_hash, company_code, created_at, updated_at) VALUES ($1, $2, $3, $4, NOW(), NOW()) RETURNING *`, @@ -197,6 +209,7 @@ async createUser(userData: CreateUserDto) { ### 예시 3: 비밀번호 변경 **변경 전**: + ```typescript async changePassword( userId: number, @@ -230,6 +243,7 @@ async changePassword( ``` **변경 후**: + ```typescript async changePassword( userId: number, @@ -257,7 +271,7 @@ async changePassword( const newPasswordHash = await bcrypt.hash(newPassword, 10); await query( - `UPDATE users + `UPDATE users SET password_hash = $1, updated_at = NOW() WHERE user_id = $2`, [newPasswordHash, userId] @@ -270,6 +284,7 @@ async changePassword( ## 🔧 기술적 고려사항 ### 1. 비밀번호 보안 + ```typescript import bcrypt from "bcrypt"; @@ -282,15 +297,19 @@ const isValid = await bcrypt.compare(plainPassword, passwordHash); ``` ### 2. SQL 인젝션 방지 + ```typescript // ❌ 위험: 직접 문자열 결합 const sql = `SELECT * FROM users WHERE username = '${username}'`; // ✅ 안전: 파라미터 바인딩 -const user = await queryOne(`SELECT * FROM users WHERE username = $1`, [username]); +const user = await queryOne(`SELECT * FROM users WHERE username = $1`, [ + username, +]); ``` ### 3. 세션 토큰 관리 + ```typescript import crypto from "crypto"; @@ -306,6 +325,7 @@ await query( ``` ### 4. 권한 검증 + ```typescript async checkPermission(userId: number, permission: string): Promise { const result = await queryOne<{ has_permission: boolean }>( @@ -323,9 +343,51 @@ async checkPermission(userId: number, permission: string): Promise { --- -## 📝 전환 체크리스트 +## ✅ 전환 완료 내역 (Phase 1.5에서 이미 완료됨) + +AuthService는 Phase 1.5에서 이미 Raw Query로 전환이 완료되었습니다. + +### 전환된 Prisma 호출 (5개) + +1. **`loginPwdCheck()`** - 로그인 비밀번호 검증 + - user_info 테이블에서 비밀번호 조회 + - EncryptUtil을 활용한 비밀번호 검증 + - 마스터 패스워드 지원 + +2. **`insertLoginAccessLog()`** - 로그인 로그 기록 + - login_access_log 테이블에 INSERT + - 로그인 시간, IP 주소 등 기록 + +3. **`getUserInfo()`** - 사용자 정보 조회 + - user_info 테이블 조회 + - PersonBean 객체로 반환 + +4. **`updateLastLoginDate()`** - 마지막 로그인 시간 업데이트 + - user_info 테이블 UPDATE + - last_login_date 갱신 + +5. **`checkUserPermission()`** - 사용자 권한 확인 + - user_auth 테이블 조회 + - 권한 코드 검증 + +### 주요 기술적 특징 + +- **보안**: EncryptUtil을 활용한 안전한 비밀번호 검증 +- **JWT 토큰**: JwtUtils를 활용한 토큰 생성 및 검증 +- **로깅**: 상세한 로그인 이력 기록 +- **에러 처리**: 안전한 에러 메시지 반환 + +### 코드 상태 + +- [x] Prisma import 없음 +- [x] query 함수 사용 중 +- [x] TypeScript 컴파일 성공 +- [x] 보안 로직 유지 + +## 📝 원본 전환 체크리스트 + +### 1단계: Prisma 호출 전환 (✅ Phase 1.5에서 완료) -### 1단계: Prisma 호출 전환 - [ ] `login()` - 사용자 조회 + 비밀번호 검증 (findFirst) - [ ] `getUserInfo()` - 사용자 정보 조회 (findUnique) - [ ] `createUser()` - 사용자 생성 (create with 중복 검사) @@ -333,12 +395,14 @@ async checkPermission(userId: number, permission: string): Promise { - [ ] `manageSession()` - 세션 관리 (create/update/delete) ### 2단계: 보안 검증 + - [ ] 비밀번호 해싱 로직 유지 (bcrypt) - [ ] SQL 인젝션 방지 확인 - [ ] 세션 토큰 보안 확인 - [ ] 중복 계정 방지 확인 ### 3단계: 테스트 + - [ ] 단위 테스트 작성 (5개) - [ ] 로그인 성공/실패 테스트 - [ ] 사용자 생성 테스트 @@ -352,6 +416,7 @@ async checkPermission(userId: number, permission: string): Promise { - [ ] 통합 테스트 작성 (2개) ### 4단계: 문서화 + - [ ] 전환 완료 문서 업데이트 - [ ] 보안 가이드 업데이트 @@ -363,7 +428,6 @@ async checkPermission(userId: number, permission: string): Promise { - 보안 크리티컬 (비밀번호, 세션) - SQL 인젝션 방지 필수 - 철저한 테스트 필요 - - **예상 소요 시간**: 1.5~2시간 - Prisma 호출 전환: 40분 - 보안 검증: 40분 @@ -374,6 +438,7 @@ async checkPermission(userId: number, permission: string): Promise { ## ⚠️ 주의사항 ### 보안 필수 체크리스트 + 1. ✅ 모든 사용자 입력은 파라미터 바인딩 사용 2. ✅ 비밀번호는 절대 평문 저장 금지 (bcrypt 사용) 3. ✅ 세션 토큰은 충분히 길고 랜덤해야 함 @@ -385,4 +450,3 @@ async checkPermission(userId: number, permission: string): Promise { **상태**: ⏳ **대기 중** **특이사항**: 보안 크리티컬, 비밀번호 암호화, 세션 관리 포함 **⚠️ 주의**: 이 서비스는 보안에 매우 중요하므로 신중한 테스트 필수! - diff --git a/PRISMA_TO_RAW_QUERY_MIGRATION_PLAN.md b/PRISMA_TO_RAW_QUERY_MIGRATION_PLAN.md index 0abb663d..44b28f7e 100644 --- a/PRISMA_TO_RAW_QUERY_MIGRATION_PLAN.md +++ b/PRISMA_TO_RAW_QUERY_MIGRATION_PLAN.md @@ -138,7 +138,7 @@ backend-node/ (루트) - `ddlAuditLogger.ts` (0개) - ✅ **전환 완료** (Phase 3.11) - [계획서](PHASE3.11_DDL_AUDIT_LOGGER_MIGRATION.md) - `externalCallConfigService.ts` (0개) - ✅ **전환 완료** (Phase 3.12) - [계획서](PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md) - `entityJoinService.ts` (0개) - ✅ **전환 완료** (Phase 3.13) - [계획서](PHASE3.13_ENTITY_JOIN_SERVICE_MIGRATION.md) -- `authService.ts` (5개) - 사용자 인증 - [계획서](PHASE3.14_AUTH_SERVICE_MIGRATION.md) +- `authService.ts` (0개) - ✅ **전환 완료** (Phase 1.5에서 완료) - [계획서](PHASE3.14_AUTH_SERVICE_MIGRATION.md) - **배치 관련 서비스 (24개)** - [통합 계획서](PHASE3.15_BATCH_SERVICES_MIGRATION.md) - `batchExternalDbService.ts` (8개) - 배치 외부DB - `batchExecutionLogService.ts` (7개) - 배치 실행 로그