# Auth 로그인/로그아웃 플로우 정리 및 종량제(CI4) 적용 방안 slow-auth-application의 로그인/로그아웃이 어떻게 동작하는지 정리하고, 종량제 프로젝트(CI4)에 어떻게 적용할지 매핑한 문서입니다. --- ## 1. Auth 로그인 플로우 (현재 구조) ### 1.1 진입점 - **URL**: `GET /auth/login` - **컨트롤러**: `Auth::login()` - **전제**: - 이미 `logged_in` 세션이 있으면 → `/access` 로 리다이렉트 (재로그인 불필요) - `?is_logout=1` 이면 → `/auth/logout` 으로 보냄 ### 1.2 폼 제출 (POST /auth/login) 1. **입력 검증** - `mb_id`(아이디): required - `mb_passwd`: required, min 4, max 20 - 실패 시 → 로그인 뷰 다시 + `form_validation->error_array()` 로 에러 표시 2. **회원 조회** - `access_get_member_info($mb_id, $auth_data)` 호출 - **auth는 3종 계정** 지원: - `@` 없음 → **member** (일반 회원): `member_m->login()` 으로 `member` 테이블 조회 - `@` 있음 → **group** 또는 **entity**: `member_group_m`, `member_entity_m` 로 그룹/엔티티 로그인 - 조회 실패 → `access_log($msg, false, $mb_id)` 로 실패 로그, 로그인 화면으로 alert 후 복귀 3. **추가 검사 (member일 때만 해당)** - 기간 설정 그룹: `gp_period_yn`, `gp_startdate`, `gp_enddate` 로 이용 기간 체크 → 밖이면 "unauthorized" 로그 + 실패 - `member_type == "group"` 이면 임시 차단 메시지 + 실패 - **비밀번호**: `password_verify($auth_data['mb_passwd'], $result->mb_passwd)` 로 검증 - **상태**: `mb_state != 1` 이면 "탈퇴/정지" 메시지 + 실패, `access_log` 기록 4. **로그인 성공** - `access_login_success($result)` 호출: - `access_set_token()`: JWT 생성, `access_token` 테이블에 저장, **세션에 토큰 저장** - `access_log("You are logged in.", true, ...)` → `member_log` 테이블에 **로그인 성공 로그** (1시간 내 중복 로그인은 한 건만 저장) - 세션에 저장: `userinfo`, `depart`(mb_group), `access_token`, `lang`, `logged_in`, `last_activity` - `access_update_latest_data()`: member/group/entity 별로 `mb_latestdate` 등 최근 로그인 시간 업데이트 - **응답**: - AJAX(`is_ajax=true`)면: JSON `{ result:1, redirect, token }` 반환, 클라이언트가 `localStorage`에 토큰 저장 후 `redirect` 로 이동 - 일반 폼이면: `redirect('/access')` 5. **실패 시** - "Please check your email and password." 등 메시지 + `access_log(..., false)` → 로그인 화면으로 ### 1.3 로그인 후 첫 화면 (Access) - **기본 라우트**: `$route['default_controller'] = 'access'` → `Access::index()` - **동작**: - 세션에 `userinfo` 없으면 → `/auth/logout` 으로 보냄 - `access_token` 과 DB의 `access_token` 테이블 비교해서 유효한 토큰인지 확인 (super admin은 별도 처리) - 유효하면 `Access::main()` → 접근 가능한 앱 목록(`access_list`)을 보여주는 **앱 선택 화면** (`_access_view("/access_v")`) - 앱이 1개면 해당 앱 URL로 바로 이동 ### 1.4 로그아웃 (GET/POST /auth/logout) 1. 세션에서 `access_token` 취득 2. **토큰이 있으면**: - `member_log_m->update_logout_item_by_token($token)` → 해당 로그인 로그에 **로그아웃 시각** 저장 - `access_token_m->item_delete_by_token($token)` → DB에서 토큰 삭제 3. `?is_logout=1` 이면 클라이언트에 `localStorage.clear()` 스크립트 출력 (자동 로그인 토큰 제거) 4. `$this->session->sess_destroy()` 로 세션 파기 5. `replace('/auth/login')` → 로그인 페이지로 이동 ### 1.5 보호 구간 (로그인 필수) - **SL_Controller** 상속 컨트롤러에서 `_setting_view()`, `_access_view()`, `_modal_view()` 등은 내부에서 `_require_login()` 호출 - `_require_login()`: `logged_in` 세션이 없으면 "로그인화면으로 이동합니다." alert 후 `/auth/logout` 으로 보냄 (결국 로그인 페이지) ### 1.6 로그 저장 구조 (member_log) - **저장 시점**: 로그인 시도(성공/실패), 로그인 성공 시 "You are logged in." 한 번, 로그아웃 시 `mll_logout_date` 업데이트 - **필드 예**: `mll_ip`, `mll_useragent`, `mb_id`, `mb_idx`, `gp_idx`, `mll_success`, `mll_msg`, `mll_url`, `mll_country`, `at_token`, `mll_regdate`, `mll_logout_date` 등 --- ## 2. 종량제(CI4)에 적용할 때 매핑 ### 2.1 줄이기 / 빼기 | Auth 기능 | 종량제 적용 | |-----------|-------------| | 3종 계정 (member / group / entity) | **1종만**: 일반 사용자(member)만. group/entity 로그인 제거 | | JWT + access_token 테이블 (자동 로그인·다중 세션) | **Phase 1에서는 제거**: 세션만 사용. 필요 시 Phase 2 이후에 "Remember me" 단순 구현 | | Access 앱 선택 화면 | **대체**: 로그인 성공 시 `/dashboard`(또는 `/admin`)로 바로 이동. 앱 목록 불필요 | | access_get_country(), GeoIP | **제거** 또는 나중에: 로그에는 IP만 저장 | | 1시간 내 중복 로그인 로그 억제 | **선택**: Phase 1에서는 매 로그인마다 로그 저장해도 무방 | | 기간/그룹 차단 로직 | **Phase 1에서는 제거**. Phase 2에서 권한/상태만 적용 | ### 2.2 그대로 가져올 개념 (동작만 CI4로 구현) | 항목 | auth | 종량제(CI4) | |------|------|-------------| | 로그인 폼 | `mb_id`, `mb_passwd`, return_url, token(CSRF) | 동일. `login_id`, `password`, CI4 CSRF | | 회원 조회 | `member_m->login()` → mb_id로 1건 | `UserModel::findByLoginId($loginId)` | | 비밀번호 검증 | `password_verify()` | 동일 | | 상태 체크 | `mb_state == 1` | `status` 활성만 허용 | | 성공 시 세션 | userinfo, logged_in, (access_token) | `user`(또는 userinfo), `logged_in` | | 로그인 로그 | `member_log` insert (성공/실패) | `login_attempts` 또는 `audit_logs` 에 INSERT | | 로그아웃 시 | member_log에 logout 시각 update, 세션 destroy | 로그아웃 로그 1건 INSERT + 세션 destroy | | 로그인 필수 체크 | `_require_login()` → 없으면 /auth/logout | **Filter** `auth`: 세션 없으면 redirect to `/login` | ### 2.3 CI4에서 구현할 흐름 (Phase 1) 1. **GET /login** - 이미 로그인됐으면 → `/dashboard` 리다이렉트 - 아니면 로그인 뷰 표시 (auth의 login_v 참고해 레이아웃만 단순화) 2. **POST /login** - Validation: `login_id`, `password` 필수 - `UserModel::findByLoginId(login_id)` - 없으면 → 실패 로그 저장, "아이디 또는 비밀번호를 확인해 주세요." → 로그인 화면 - 있으면 → `password_verify(password, user->password_hash)` - 실패 → 실패 로그, 동일 메시지 - 활성 상태 아님 → "중지된 계정입니다." 등 - 성공 → - 세션에 `user`(id, login_id, name, role 등), `logged_in = true` - 로그인 성공 로그 INSERT (IP, user_agent, user_id, success) - (선택) `users.last_login_at` UPDATE - redirect to `/dashboard` 3. **POST /logout** - (선택) 로그아웃 로그 INSERT (user_id, action=LOGOUT) - `session()->destroy()` - redirect to `/login` 4. **Filter `auth`** - URI가 `login` 이면 통과 - 그 외: 세션에 `logged_in` 없으면 redirect to `/login` - 필요한 라우트에만 `filter('auth')` 적용 (또는 전역 적용 후 login만 제외) 5. **대시보드** - `GET /dashboard` → Filter auth 통과 후, 단순 대시 뷰 (나중에 Phase 2에서 admin 메뉴로 교체) --- ## 3. 정리 - **Auth의 로그인/로그아웃 플로우**는 “폼 검증 → 회원 조회 → 비밀번호/상태 검사 → 세션 + 토큰 + 로그 기록 → 리다이렉트”이고, 로그아웃은 “토큰/로그 업데이트 + 세션 파기”입니다. - **종량제 Phase 1**에서는 위 플로우 중 **세션 기반 로그인/로그아웃 + 로그인(성공/실패) 로그**만 동일하게 구현하고, **JWT·access_token·3종 계정·Access 앱 선택 화면**은 쓰지 않습니다. - 이렇게 하면 auth와 **동작 느낌(로그인 → 대시로 이동, 로그인 필수 구간 보호)**은 맞추면서, CI4 구조에 맞게 단순하게 가져갈 수 있습니다. --- ## 4. 회원가입 / 계정 생성 정책 (요구사항 기준 초안) - CSV와 현재 문서 기준으로 보면, **명시된 역할은 4가지**입니다. - `super admin` / `지자체관리자` / `지정판매소` / `일반 사용자(시민)` - 이 중에서 **업무용 계정(super admin, 지자체, 지정판매소)** 은 - **관리자가 “사용자 관리(PWB-020201)” 화면에서 등록**하고, - 브라우저에서 자체 등록한 계정이 있다면 **권한 승인(PWB-020301)** 으로 승인하는 흐름을 사용합니다. - **일반 사용자(시민)** 는 현재 요구사항에서 **로그인 기반 기능이 “정품 바코드 확인” 정도** 뿐이고, “시민이 직접 회원가입해야 한다”는 명시는 없습니다. - 따라서 **지금 요구사항만 놓고 보면**: - **일반 사용자는 필수 회원가입 없이 앱을 쓸 수 있게 하고**, - **관리자·지자체·지정판매소 계정은 관리자 등록 + (옵션) 권한 승인** 구조로 가는 것이 자연스럽습니다. - 시민 회원가입/로그인(예: 마이페이지, 신고 이력 관리 등)이 실제로 필요해지는 시점에, 별도의 **시민 회원가입/인증 플로우를 설계**하는 쪽이 더 안전합니다.