cms-orbit/password-security
最新稳定版本:1.1.3
Composer 安装命令:
composer require cms-orbit/password-security
包简介
Laravel password security package with comprehensive validation rules for strong password policies
README 文档
README
Laravel 애플리케이션을 위한 포괄적인 패스워드 보안 관리 패키지입니다. 강력한 패스워드 정책, 만료 관리, 휴면 계정 처리 등의 기능을 제공합니다.
주요 기능
🔐 패스워드 복잡도 검증
- 영문 대문자, 소문자, 숫자, 특수문자 조합 규칙
- 2가지 조합 시 10자 이상, 3가지 이상 조합 시 8자 이상
- 커스터마이징 가능한 복잡도 규칙
🚫 일반 패턴 차단
- 연속된 숫자/문자 차단 (123456, abcdef 등)
- 키보드 패턴 차단 (qwerty, asdfgh 등)
- 반복 문자 차단 (aaaaaa, 111111 등)
- 생일/전화번호 패턴 차단
- 일반적인 단어 차단 (password, admin 등)
👤 개인정보 보호
- 이름, 이메일, 사용자명 포함 차단
- 대소문자 구분 없는 검사
- 추가 개인정보 필드 커스터마이징
📜 패스워드 히스토리 관리
- 최근 N개 패스워드 재사용 방지
- 자동 히스토리 정리
- IP 주소 및 User Agent 기록
⏰ 패스워드 만료 관리
- 분기(90일) 단위 패스워드 변경 강제
- 만료 전 알림 (7일, 3일, 1일 전)
- 만료 시 자동 리다이렉션
- 유예 기간 설정 가능
💤 휴면 계정 관리
- 일정 기간 미사용 계정 자동 비활성화
- 비활성화 전 알림 발송 (14일, 7일, 3일 전)
- 비활성화 후 자동 삭제 (설정 가능)
- SoftDeletes 모델의 강제삭제 지원
- 역할 및 이메일 기반 제외 규칙
- Central/Tenant 모델 지원
- Chunk 처리 및 상세 진행 상황 표시
🔔 알림 시스템
- 패스워드 만료 알림
- 휴면 계정 알림
- 다중 채널 지원 (메일, 데이터베이스 등)
🛠️ 개발자 친화적
- Laravel Nova 통합 지원
- 쉬운 모델 통합 (Trait 기반)
- 커스터마이징 가능한 뷰
- 다국어 지원 (한국어, 영어)
요구사항
- PHP 8.2 이상
- Laravel 9.x, 10.x, 11.x
- MySQL 5.7+ 또는 PostgreSQL 9.6+
설치
1. Composer로 설치
composer require cms-orbit/password-security
2. 설정 파일 발행
php artisan vendor:publish --tag=password-security-config php artisan vendor:publish --tag=password-security-migrations php artisan vendor:publish --tag=password-security-views php artisan vendor:publish --tag=password-security-lang
3. 마이그레이션 실행
php artisan migrate
기본 사용법
1. 모델에 Trait 추가
패스워드 보안 기능을 사용할 모델에 HasPasswordSecurity Trait을 추가합니다.
<?php namespace App\Models; use CmsOrbit\PasswordSecurity\Traits\HasPasswordSecurity; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use HasPasswordSecurity; // 패스워드 필드명 (기본값: 'password') protected $passwordSecurityField = 'password'; // 개인정보 필드 (패스워드에 포함 방지) protected $passwordSecurityPersonalFields = [ 'name', 'email', 'username', ]; }
2. 설정 파일에 모델 등록
config/password-security.php 파일에서 모델을 등록합니다.
'models' => [ \App\Models\User::class, // 다른 모델 추가... ],
3. 미들웨어 적용
전역 적용 (app/Http/Kernel.php)
protected $middlewareGroups = [ 'web' => [ // ... \CmsOrbit\PasswordSecurity\Middleware\CheckPasswordExpiration::class, \CmsOrbit\PasswordSecurity\Middleware\CheckAccountActive::class, ], ];
라우트 그룹에 적용
Route::middleware(['auth', 'password.expiration', 'account.active'])->group(function () { // 보호된 라우트들... });
4. Validation Rule 사용
일반 폼 검증
use CmsOrbit\PasswordSecurity\Rules\PasswordSecurityRule; $request->validate([ 'password' => ['required', new PasswordSecurityRule($user)], ]);
Laravel Nova 통합
use CmsOrbit\PasswordSecurity\Rules\PasswordSecurityRule; use Laravel\Nova\Fields\Password; Password::make('Password', 'password') ->rules('required', new PasswordSecurityRule($this->resource)) ->creationRules('required') ->updateRules('nullable');
고급 사용법
패스워드 검증 커스터마이징
use CmsOrbit\PasswordSecurity\Validators\PasswordValidator; $validator = new PasswordValidator(); try { $validator->validate($password, $user, true); // 검증 성공 } catch (\CmsOrbit\PasswordSecurity\Exceptions\WeakPasswordException $e) { // 검증 실패 $errors = $e->getErrors(); $message = $e->getMessage(); }
개별 규칙 검증
$validator = new PasswordValidator(); // 복잡도만 검증 if (!$validator->validateComplexity($password)) { // 복잡도 검증 실패 } // 일반 패턴만 검증 if (!$validator->validateCommonPattern($password)) { // 일반 패턴 검증 실패 } // 개인정보만 검증 if (!$validator->validatePersonalInfo($password, $user)) { // 개인정보 검증 실패 } // 히스토리만 검증 if (!$validator->validateHistory($password, $user)) { // 히스토리 검증 실패 }
모델 메서드 사용
// 패스워드 만료 확인 if ($user->isPasswordExpired()) { // 만료됨 } // 만료까지 남은 일수 $daysRemaining = $user->getDaysUntilPasswordExpiration(); // 계정 활성화 상태 확인 if ($user->isAccountActive()) { // 활성화됨 } // 계정 비활성화 $user->deactivateAccount('inactivity'); // 계정 활성화 $user->activateAccount(); // 패스워드 히스토리 확인 if ($user->isPasswordInHistory($newPassword)) { // 최근 사용한 패스워드 } // 마지막 로그인 업데이트 $user->updateLastLogin(); // 휴면 계정 관리 (HasFreezePolicy trait 사용 시) // 계정이 휴면 상태인지 확인 if ($user->isFrozen()) { // 휴면 상태 } // 계정을 휴면 상태로 설정 $user->freeze(); // 계정을 활성 상태로 복구 $user->unfreeze(); // 활성화 상태 기준일 가져오기 $baseDate = $user->getDaysUntilFreeze(); // 휴면 기준일 가져오기 $inactiveDays = $user->getFreezeInactiveDays(); // 비활성화 전 알림 일자들 가져오기 $notifyBeforeDays = $user->getFreezeNotifyBeforeDays(); // 제외 여부 확인 if ($user->isExclusion()) { // 휴면 대상에서 제외됨 }
Artisan 명령어
패스워드 만료 알림 발송
# 일반 실행 php artisan password-security:notify-expiration # Dry-run (실제 발송 없이 확인) php artisan password-security:notify-expiration --dry-run # 만료된 계정에 강제 변경 플래그 설정 php artisan password-security:notify-expiration --force-change
휴면 계정 관리
# 일반 실행 php artisan password-security:freeze # Dry-run (실제 처리 없이 확인) php artisan password-security:freeze --dry-run # 비활성화 전 알림 발송 php artisan password-security:freeze --notify
이 명령어는 다음 작업을 수행합니다:
- 비활성화: 기준일 + 휴면기준일이 지난 활성 계정을 비활성화
- 삭제: 비활성화 후 삭제기간이 지난 계정을 삭제
- 강제삭제: SoftDeletes 모델에서 강제삭제기간이 지난 소프트 삭제된 계정을 완전 삭제
- 알림: 비활성화 전 알림 대상자에게 알림 발송
명령어 실행 시 각 모델별로 100개씩 chunk로 처리하며, 각 chunk마다 상세한 진행 상황을 테이블로 표시합니다.
스케줄러 설정
패키지는 자동으로 스케줄러를 등록합니다. app/Console/Kernel.php에 추가 설정이 필요하지 않습니다.
- 매일 오전 2시: 휴면 계정 관리 (
password-security:freeze) - 매일 오전 9시: 패스워드 만료 알림 (
password-security:notify-expiration)
스케줄러를 실행하려면 cron에 다음을 추가하세요:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
설정 옵션
패스워드 복잡도 설정
'complexity' => [ 'enabled' => true, 'min_length_2_types' => 10, // 2가지 조합 시 최소 길이 'min_length_3_types' => 8, // 3가지 조합 시 최소 길이 'min_length_4_types' => 8, // 4가지 조합 시 최소 길이 'require_uppercase' => true, // 대문자 필수 'require_lowercase' => true, // 소문자 필수 'require_numbers' => true, // 숫자 필수 'require_special' => true, // 특수문자 필수 'special_characters' => '!@#$%^&*()_+-=[]{}|;:,.<>?~`', ],
일반 패턴 차단 설정
'common_patterns' => [ 'enabled' => true, 'block_sequential_numbers' => true, // 연속 숫자 차단 'block_sequential_letters' => true, // 연속 문자 차단 'block_repeated_characters' => true, // 반복 문자 차단 'repeated_char_threshold' => 3, // 반복 허용 횟수 'block_keyboard_patterns' => true, // 키보드 패턴 차단 'block_common_words' => true, // 일반 단어 차단 'block_birthday_patterns' => true, // 생일 패턴 차단 'block_phone_patterns' => true, // 전화번호 패턴 차단 'sequential_threshold' => 3, // 연속 허용 개수 'common_words_list' => [...], // 차단할 단어 목록 'keyboard_patterns' => [...], // 키보드 패턴 목록 ],
개인정보 차단 설정
'personal_info' => [ 'enabled' => true, 'block_name' => true, // 이름 포함 차단 'block_email' => true, // 이메일 포함 차단 'block_username' => true, // 사용자명 포함 차단 'additional_fields' => [], // 추가 차단 필드 'min_substring_length' => 3, // 최소 부분 문자열 길이 'case_insensitive' => true, // 대소문자 구분 없음 ],
패스워드 히스토리 설정
'history' => [ 'enabled' => true, 'check_last_n_passwords' => 3, // 최근 N개 체크 'keep_history_for_days' => 365, // 보관 기간 'auto_cleanup' => true, // 자동 정리 ],
패스워드 만료 설정
'expiration' => [ 'enabled' => true, 'expires_in_days' => 90, // 만료 기간 (분기) 'notify_before_days' => [7, 3, 1], // 만료 전 알림 'grace_period_days' => 0, // 유예 기간 'force_change_on_first_login' => false, // 첫 로그인 강제 변경 'redirect_after_change' => '/', // 변경 후 리다이렉트 'excluded_routes' => [...], // 제외 라우트 'excluded_urls' => [...], // 제외 URL 패턴 ],
휴면 계정 설정
'inactive_accounts' => [ 'enabled' => true, 'target_models' => [ \AppCentral\Models\User::class, ], 'target_tenant_models' => [ \AppTenants\Models\Promoter::class, ], ],
각 모델에서 HasFreezePolicy trait를 사용하여 개별 설정이 가능합니다:
use CmsOrbit\PasswordSecurity\Traits\HasFreezePolicy; class User extends Authenticatable { use HasFreezePolicy; // 휴면 기준일 (기본값: 90일) protected $freezeInactiveDays = 90; // 또는 메서드로 public function getFreezeInactiveDays(): int { return 90; } // 비활성화 전 알림 일자들 (기본값: [14, 7, 3]) protected $freezeNotifyBeforeDays = [14, 7, 3]; // 비활성화 후 삭제기간 (기본값: 7일, null이면 삭제 안 함) protected $freezeDeleteAfterDays = 7; // 강제삭제 기간 (SoftDeletes 모델용, 기본값: 5일) protected $freezeForceDeleteAfterDays = 5; // 계정활성화 상태 필드명 (기본값: 'is_freeze') protected $freezeStatusField = 'is_freeze'; // 휴면대상에서 제외할 모델인지 판별 public function isExclusion(): bool { // 특정 조건에 따라 제외 return $this->hasRole('admin'); } // 활성화 상태 기준일 반환 (마지막 로그인일 또는 생성일) public function getDaysUntilFreeze(): \Carbon\Carbon { $lastLoginAt = $this->lastLoginAt(); return $lastLoginAt ? \Carbon\Carbon::parse($lastLoginAt) : $this->created_at; } }
알림 설정
'notifications' => [ 'enabled' => true, 'channels' => ['mail'], // 알림 채널 'expiration' => [ 'enabled' => true, 'mail_subject' => 'Password Expiration Notice', ], 'inactive_account' => [ 'enabled' => true, 'mail_subject' => 'Account Inactivity Notice', ], ],
뷰 커스터마이징
패스워드 변경 화면
패키지가 제공하는 기본 뷰를 커스터마이징할 수 있습니다.
php artisan vendor:publish --tag=password-security-views
발행된 뷰는 resources/views/vendor/password-security/ 디렉토리에 생성됩니다.
password-change.blade.php: 패스워드 변경 화면account-inactive.blade.php: 휴면 계정 화면
설정 파일에서 뷰 경로를 변경할 수도 있습니다:
'views' => [ 'password_change' => 'password-security::password-change', 'account_inactive' => 'password-security::account-inactive', ],
다국어 지원
패키지는 한국어와 영어를 기본 지원합니다.
php artisan vendor:publish --tag=password-security-lang
발행된 언어 파일은 resources/lang/vendor/password-security/ 디렉토리에 생성됩니다.
예외 처리
사용 가능한 예외
WeakPasswordException: 약한 패스워드 (복잡도, 패턴 등)PasswordReusedException: 패스워드 재사용PasswordExpiredException: 패스워드 만료
예외 처리 방식 설정
'exceptions' => [ 'throw_exceptions' => true, // Exception 발생 여부 'log_violations' => true, // 위반 사항 로그 기록 'log_channel' => null, // 로그 채널 ],
throw_exceptions를 false로 설정하면 예외 대신 validation error를 반환합니다.
데이터베이스 테이블
패키지는 두 개의 테이블을 생성합니다:
password_securities
사용자의 패스워드 보안 정보를 저장합니다.
securable_type,securable_id: 다형성 관계password_changed_at: 마지막 패스워드 변경 일시password_expires_at: 패스워드 만료 일시password_must_change: 강제 변경 플래그last_login_at: 마지막 로그인 일시is_active: 계정 활성화 상태deactivated_at: 비활성화 일시deactivation_reason: 비활성화 사유
password_histories
패스워드 변경 히스토리를 저장합니다.
securable_type,securable_id: 다형성 관계password_hash: 패스워드 해시changed_at: 변경 일시changed_by: 변경한 사용자ip_address: IP 주소user_agent: User Agent
테스트
cd packages/password-security
composer install
./vendor/bin/phpunit
보안 취약점 보고
보안 취약점을 발견하시면 dev@cms-orbit.com으로 이메일을 보내주세요. 모든 보안 취약점은 신속하게 해결됩니다.
라이선스
MIT 라이선스입니다. 자세한 내용은 LICENSE 파일을 참조하세요.
크레딧
- CMS Orbit Development Team
- 모든 기여자들
변경 이력
1.1.3 (2025-12-06)
- 알림 즉시 발송 기능 추가
- Notification::sendNow() 사용으로 큐 없이 즉시 발송
- ShouldQueue 인터페이스로 인한 지연 발송 문제 해결
1.1.2 (2025-12-06)
- deactivateUser() 메서드에서도 Notification 파사드 사용으로 변경
- 알림 발송 실패 시 예외 처리 개선
1.1.1 (2025-12-06)
- 알림 발송 로직 개선
- Notification 파사드를 통한 알림 발송으로 변경
- 알림 발송 실패 시 예외 처리 추가
- --notify 옵션 없이도 알림이 활성화되어 있으면 자동 발송
1.1.0 (2025-12-06)
- 휴면 계정 관리 기능 대폭 개선
HasFreezePolicytrait 추가- 모델별 개별 휴면 정책 설정 지원
- 비활성화 후 자동 삭제 기능
- SoftDeletes 모델의 강제삭제 지원
- Central/Tenant 모델 지원
- Chunk 처리 및 상세 진행 상황 표시
password-security:freeze명령어로 통합is_freeze필드 기반 휴면 상태 관리getDaysUntilFreeze()메서드로 기준일 관리isExclusion()메서드로 제외 규칙 커스터마이징
1.0.0 (2025-01-12)
- 최초 안정 버전 릴리스
- 패스워드 복잡도 검증
- 일반 패턴 차단
- 개인정보 포함 차단
- 패스워드 히스토리 관리
- 패스워드 만료 관리
- 알림 시스템
统计信息
- 总下载量: 2
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 0
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-11-12