feat: TOTP 2차 인증, 관리자 메뉴/대시보드 및 의존성 반영
- robthree/twofactorauth, Auth 설정·TotpService·2FA 뷰·라우트 - member TOTP 컬럼 DDL(login_tables, member_add_totp.sql) - 관리자 메뉴·레이아웃·필터·대시보드 등 연관 변경 - env 샘플에 auth.requireTotp 주석 Made-with: Cursor
This commit is contained in:
52
app/Config/Auth.php
Normal file
52
app/Config/Auth.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Config;
|
||||
|
||||
use CodeIgniter\Config\BaseConfig;
|
||||
|
||||
/**
|
||||
* 로그인·2차 인증(TOTP) 관련 설정
|
||||
*
|
||||
* .env 예:
|
||||
* auth.requireTotp = true
|
||||
* auth.totpIssuer = "쓰레기봉투 물류시스템"
|
||||
*/
|
||||
class Auth extends BaseConfig
|
||||
{
|
||||
/** 운영·스테이징 true 권장. 로컬 개발 시 false 로 1단계만 로그인 가능 */
|
||||
public bool $requireTotp = true;
|
||||
|
||||
/** 인증 앱에 표시되는 발급자(issuer) */
|
||||
public string $totpIssuer = '쓰레기봉투 물류시스템';
|
||||
|
||||
/** TOTP 연속 실패 시 세션 종료 전 허용 횟수 */
|
||||
public int $totpMaxAttempts = 5;
|
||||
|
||||
/** 비밀번호 통과 후 2단계 완료까지 허용 시간(초) */
|
||||
public int $pending2faTtlSeconds = 600;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$require = env('auth.requireTotp');
|
||||
if ($require !== null && $require !== '') {
|
||||
$this->requireTotp = filter_var($require, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
$issuer = env('auth.totpIssuer');
|
||||
if (is_string($issuer) && $issuer !== '') {
|
||||
$this->totpIssuer = $issuer;
|
||||
}
|
||||
|
||||
$max = env('auth.totpMaxAttempts');
|
||||
if ($max !== null && $max !== '' && is_numeric($max)) {
|
||||
$this->totpMaxAttempts = max(1, (int) $max);
|
||||
}
|
||||
|
||||
$ttl = env('auth.pending2faTtlSeconds');
|
||||
if ($ttl !== null && $ttl !== '' && is_numeric($ttl)) {
|
||||
$this->pending2faTtlSeconds = max(60, (int) $ttl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@ class Roles extends BaseConfig
|
||||
* mb_level 상수 (member.mb_level)
|
||||
*/
|
||||
public const LEVEL_SUPER_ADMIN = 4;
|
||||
/** 본부 관리자 — 현재는 super admin과 동일한 관리자 권한(지자체 선택 후 작업). 추후 super 전용 기능 분리 시 여기만 조정 */
|
||||
public const LEVEL_HEADQUARTERS_ADMIN = 5;
|
||||
public const LEVEL_LOCAL_ADMIN = 3; // 지자체관리자
|
||||
public const LEVEL_SHOP = 2; // 지정판매소
|
||||
public const LEVEL_CITIZEN = 1; // 일반 사용자(시민)
|
||||
@@ -29,8 +31,27 @@ class Roles extends BaseConfig
|
||||
self::LEVEL_SHOP => '지정판매소',
|
||||
self::LEVEL_LOCAL_ADMIN => '지자체관리자',
|
||||
self::LEVEL_SUPER_ADMIN => 'super admin',
|
||||
self::LEVEL_HEADQUARTERS_ADMIN => '본부 관리자',
|
||||
];
|
||||
|
||||
/**
|
||||
* super admin(4) 또는 본부 관리자(5) — 동일 관리자 UX(지자체 선택 등)에 사용
|
||||
*/
|
||||
public static function isSuperAdminEquivalent(int $level): bool
|
||||
{
|
||||
return $level === self::LEVEL_SUPER_ADMIN || $level === self::LEVEL_HEADQUARTERS_ADMIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* TOTP 2차 인증 적용 대상 (지자체·super·본부 관리자)
|
||||
*/
|
||||
public static function requiresTotp(int $level): bool
|
||||
{
|
||||
return $level === self::LEVEL_LOCAL_ADMIN
|
||||
|| $level === self::LEVEL_SUPER_ADMIN
|
||||
|| $level === self::LEVEL_HEADQUARTERS_ADMIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* 자체 회원가입 시 기본 역할 (mb_level)
|
||||
*/
|
||||
|
||||
@@ -11,6 +11,7 @@ $routes->get('dashboard/classic-mock', 'Home::dashboardClassicMock');
|
||||
$routes->get('dashboard/modern', 'Home::dashboardModern');
|
||||
$routes->get('dashboard/dense', 'Home::dashboardDense');
|
||||
$routes->get('dashboard/charts', 'Home::dashboardCharts');
|
||||
$routes->get('dashboard/blend', 'Home::dashboardBlend');
|
||||
$routes->get('bag/inventory-inquiry', 'Home::inventoryInquiry');
|
||||
$routes->get('bag/waste-suibal-enterprise', 'Home::wasteSuibalEnterprise');
|
||||
|
||||
@@ -29,6 +30,10 @@ $routes->get('bag/help', 'Bag::help');
|
||||
// Auth
|
||||
$routes->get('login', 'Auth::showLoginForm');
|
||||
$routes->post('login', 'Auth::login');
|
||||
$routes->get('login/two-factor', 'Auth::showTwoFactor');
|
||||
$routes->post('login/two-factor', 'Auth::verifyTwoFactor');
|
||||
$routes->get('login/totp-setup', 'Auth::showTotpSetup');
|
||||
$routes->post('login/totp-setup', 'Auth::completeTotpSetup');
|
||||
$routes->get('logout', 'Auth::logout');
|
||||
$routes->get('register', 'Auth::showRegisterForm');
|
||||
$routes->post('register', 'Auth::register');
|
||||
|
||||
Reference in New Issue
Block a user