162 lines
9.4 KiB
Markdown
162 lines
9.4 KiB
Markdown
# 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)** 으로 승인하는 흐름을 사용합니다.
|
|
- **일반 사용자(시민)** 는 현재 요구사항에서 **로그인 기반 기능이 “정품 바코드 확인” 정도** 뿐이고, “시민이 직접 회원가입해야 한다”는 명시는 없습니다.
|
|
- 따라서 **지금 요구사항만 놓고 보면**:
|
|
- **일반 사용자는 필수 회원가입 없이 앱을 쓸 수 있게 하고**,
|
|
- **관리자·지자체·지정판매소 계정은 관리자 등록 + (옵션) 권한 승인** 구조로 가는 것이 자연스럽습니다.
|
|
- 시민 회원가입/로그인(예: 마이페이지, 신고 이력 관리 등)이 실제로 필요해지는 시점에, 별도의 **시민 회원가입/인증 플로우를 설계**하는 쪽이 더 안전합니다.
|