Files
Todo-Project/docs/SECURITY.md
Hyungi Ahn 761757c12e Initial commit: Todo Project with dashboard, classification center, and upload functionality
- 📱 PWA 지원: 홈화면 추가 가능한 Progressive Web App
- 🎨 M-Project 색상 스키마: 하늘색, 주황색, 회색, 흰색 일관된 디자인
- 📊 대시보드: 데스크톱 캘린더 뷰 + 모바일 일일 뷰 반응형 디자인
- 📥 분류 센터: Gmail 스타일 받은편지함으로 스마트 분류 시스템
- 🤖 AI 분류 제안: 키워드 기반 자동 분류 제안 및 일괄 처리
- 📷 업로드 모달: 데스크톱(파일 선택) + 모바일(카메라/갤러리) 최적화
- 🏷️ 3가지 분류: Todo(시작일), 캘린더(마감일), 체크리스트(무기한)
- 📋 체크리스트: 진행률 표시 및 완료 토글 기능
- 🔄 시놀로지 연동 준비: 메일플러스 연동을 위한 구조 설계
- 📱 반응형 UI: 모든 페이지 모바일 최적화 완료
2025-09-19 08:52:49 +09:00

388 lines
12 KiB
Markdown

# 보안 가이드 (SECURITY.md)
## 🔐 보안 철학
Todo-Project는 **개인용 도구**로 설계되어 **편의성**과 **적절한 보안** 사이의 균형을 추구합니다.
### 보안 원칙
- **Trust but Verify**: 신뢰할 수 있는 기기에서는 간편하게, 의심스러운 접근은 차단
- **최소 권한**: 필요한 최소한의 권한만 부여
- **개인 최적화**: 개인 사용에 최적화된 보안 모델
## 🛡️ 보안 레벨
### 1. Minimal (개인용 권장)
```python
SECURITY_MINIMAL = {
"device_remember_days": 30, # 30일간 기기 기억
"require_password": False, # 기기 등록 후 비밀번호 불필요
"session_timeout": 0, # 무제한 세션
"biometric_optional": True, # 생체 인증 선택사항
"auto_login": True # 자동 로그인 활성화
}
```
**적합한 환경**: 개인 기기 (내 폰, 내 컴퓨터)에서만 사용
### 2. Balanced (일반 권장)
```python
SECURITY_BALANCED = {
"device_remember_days": 7, # 7일간 기기 기억
"require_password": True, # 주기적 비밀번호 확인
"session_timeout": 24*60, # 24시간 세션
"biometric_optional": True, # 생체 인증 선택사항
"auto_login": False # 수동 로그인
}
```
**적합한 환경**: 가끔 다른 기기에서도 접근하는 경우
### 3. Secure (높은 보안)
```python
SECURITY_SECURE = {
"device_remember_days": 1, # 1일간만 기기 기억
"require_password": True, # 매번 비밀번호 확인
"session_timeout": 60, # 1시간 세션
"biometric_required": True, # 생체 인증 필수
"auto_login": False # 수동 로그인
}
```
**적합한 환경**: 민감한 정보가 포함된 경우
## 🔑 인증 시스템
### 기기 등록 방식
#### 기기 식별
```python
class DeviceFingerprint:
"""기기 고유 식별자 생성"""
def generate_fingerprint(self, request):
"""브라우저 fingerprint 생성"""
components = [
request.headers.get('User-Agent', ''),
request.headers.get('Accept-Language', ''),
request.headers.get('Accept-Encoding', ''),
self.get_screen_resolution(), # JavaScript에서 전송
self.get_timezone(), # JavaScript에서 전송
self.get_platform_info() # JavaScript에서 전송
]
fingerprint = hashlib.sha256(
'|'.join(components).encode('utf-8')
).hexdigest()
return fingerprint[:16] # 16자리 축약
```
#### 기기 등록 프로세스
```python
class DeviceRegistration:
"""기기 등록 관리"""
async def register_device(self, user_id, device_info, user_confirmation):
"""새 기기 등록"""
# 1. 사용자 확인 (비밀번호 또는 기존 기기에서 승인)
if not await self.verify_user_identity(user_id, user_confirmation):
raise AuthenticationError("사용자 확인 실패")
# 2. 기기 정보 생성
device_id = self.generate_device_id(device_info)
device_name = device_info.get('name', '알 수 없는 기기')
# 3. 장기 토큰 생성 (30일 유효)
device_token = self.create_device_token(user_id, device_id)
# 4. 기기 정보 저장
device_record = {
"device_id": device_id,
"user_id": user_id,
"device_name": device_name,
"fingerprint": device_info['fingerprint'],
"registered_at": datetime.now(),
"last_used": datetime.now(),
"token": device_token,
"expires_at": datetime.now() + timedelta(days=30),
"is_trusted": True
}
await self.save_device_record(device_record)
return device_token
```
### 토큰 관리
#### JWT 토큰 구조
```python
class TokenManager:
"""토큰 생성 및 관리"""
def create_device_token(self, user_id, device_id):
"""장기간 유효한 기기 토큰 생성"""
payload = {
"user_id": str(user_id),
"device_id": device_id,
"token_type": "device",
"issued_at": datetime.utcnow(),
"expires_at": datetime.utcnow() + timedelta(days=30)
}
return jwt.encode(payload, settings.SECRET_KEY, algorithm="HS256")
def create_session_token(self, user_id, device_id):
"""세션 토큰 생성"""
payload = {
"user_id": str(user_id),
"device_id": device_id,
"token_type": "session",
"issued_at": datetime.utcnow(),
"expires_at": datetime.utcnow() + timedelta(hours=24)
}
return jwt.encode(payload, settings.SECRET_KEY, algorithm="HS256")
```
#### 토큰 검증
```python
class TokenValidator:
"""토큰 검증"""
async def validate_device_token(self, token):
"""기기 토큰 검증"""
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
# 토큰 타입 확인
if payload.get("token_type") != "device":
return None
# 만료 시간 확인
expires_at = datetime.fromisoformat(payload["expires_at"])
if datetime.utcnow() > expires_at:
return None
# 기기 정보 확인
device_record = await self.get_device_record(
payload["user_id"],
payload["device_id"]
)
if not device_record or not device_record["is_trusted"]:
return None
return payload
except jwt.JWTError:
return None
```
## 🔒 데이터 보안
### 데이터베이스 보안
#### 비밀번호 해싱
```python
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(password: str) -> str:
"""비밀번호 해싱 (bcrypt)"""
return pwd_context.hash(password)
def verify_password(plain_password: str, hashed_password: str) -> bool:
"""비밀번호 검증"""
return pwd_context.verify(plain_password, hashed_password)
```
#### 민감 정보 암호화
```python
from cryptography.fernet import Fernet
class DataEncryption:
"""민감 정보 암호화"""
def __init__(self):
self.key = settings.ENCRYPTION_KEY.encode()
self.cipher = Fernet(self.key)
def encrypt_sensitive_data(self, data: str) -> str:
"""민감 정보 암호화 (시놀로지 비밀번호 등)"""
return self.cipher.encrypt(data.encode()).decode()
def decrypt_sensitive_data(self, encrypted_data: str) -> str:
"""민감 정보 복호화"""
return self.cipher.decrypt(encrypted_data.encode()).decode()
```
### 네트워크 보안
#### HTTPS 강제
```python
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
# 프로덕션에서 HTTPS 강제
if not settings.DEBUG:
app.add_middleware(HTTPSRedirectMiddleware)
```
#### CORS 설정
```python
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=settings.ALLOWED_ORIGINS, # 특정 도메인만 허용
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["*"],
)
```
## 🚨 보안 모니터링
### 로그인 시도 모니터링
```python
class SecurityMonitor:
"""보안 모니터링"""
def __init__(self):
self.failed_attempts = {} # IP별 실패 횟수
self.blocked_ips = set() # 차단된 IP
async def record_login_attempt(self, ip_address, success):
"""로그인 시도 기록"""
if success:
# 성공 시 실패 횟수 초기화
self.failed_attempts.pop(ip_address, None)
else:
# 실패 시 횟수 증가
self.failed_attempts[ip_address] = \
self.failed_attempts.get(ip_address, 0) + 1
# 5회 실패 시 30분 차단
if self.failed_attempts[ip_address] >= 5:
self.block_ip(ip_address, minutes=30)
def block_ip(self, ip_address, minutes=30):
"""IP 주소 차단"""
self.blocked_ips.add(ip_address)
# 일정 시간 후 차단 해제
asyncio.create_task(
self.unblock_ip_after(ip_address, minutes)
)
```
### 의심스러운 활동 감지
```python
class AnomalyDetection:
"""이상 활동 감지"""
async def detect_suspicious_activity(self, user_id, activity):
"""의심스러운 활동 감지"""
# 1. 비정상적인 시간대 접근
if self.is_unusual_time(activity.timestamp):
await self.alert_unusual_time_access(user_id, activity)
# 2. 새로운 기기에서 접근
if not await self.is_known_device(user_id, activity.device_info):
await self.alert_new_device_access(user_id, activity)
# 3. 비정상적인 API 호출 패턴
if await self.is_unusual_api_pattern(user_id, activity):
await self.alert_unusual_api_pattern(user_id, activity)
```
## 🔧 보안 설정
### 환경 변수 보안
```bash
# .env 파일 보안 설정
SECRET_KEY=your-very-long-and-random-secret-key-here
ENCRYPTION_KEY=your-32-byte-encryption-key-here
# 시놀로지 인증 정보 (암호화 저장)
SYNOLOGY_USERNAME=encrypted_username
SYNOLOGY_PASSWORD=encrypted_password
# 보안 레벨 설정
SECURITY_LEVEL=minimal # minimal, balanced, secure
ENABLE_DEVICE_REGISTRATION=true
ENABLE_BIOMETRIC_AUTH=true
ENABLE_SECURITY_MONITORING=true
# 세션 설정
SESSION_TIMEOUT_MINUTES=1440 # 24시간
DEVICE_REMEMBER_DAYS=30
```
### 보안 헤더
```python
from fastapi.middleware.trustedhost import TrustedHostMiddleware
from fastapi.responses import Response
# 신뢰할 수 있는 호스트만 허용
app.add_middleware(
TrustedHostMiddleware,
allowed_hosts=["localhost", "127.0.0.1", "your-domain.com"]
)
@app.middleware("http")
async def add_security_headers(request, call_next):
"""보안 헤더 추가"""
response = await call_next(request)
response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["X-Frame-Options"] = "DENY"
response.headers["X-XSS-Protection"] = "1; mode=block"
response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
return response
```
## 🛠️ 보안 체크리스트
### 개발 환경
- [ ] `.env` 파일이 `.gitignore`에 포함되어 있는가?
- [ ] 기본 비밀번호가 변경되었는가?
- [ ] 디버그 모드가 비활성화되어 있는가? (프로덕션)
- [ ] 로그에 민감 정보가 포함되지 않는가?
### 인증 시스템
- [ ] 비밀번호가 안전하게 해싱되어 있는가?
- [ ] JWT 토큰에 민감 정보가 포함되지 않는가?
- [ ] 토큰 만료 시간이 적절하게 설정되어 있는가?
- [ ] 기기 등록 프로세스가 안전한가?
### 네트워크 보안
- [ ] HTTPS가 활성화되어 있는가? (프로덕션)
- [ ] CORS 설정이 적절한가?
- [ ] 보안 헤더가 설정되어 있는가?
- [ ] 불필요한 포트가 차단되어 있는가?
### 데이터 보안
- [ ] 민감 정보가 암호화되어 있는가?
- [ ] 데이터베이스 접근이 제한되어 있는가?
- [ ] 백업 데이터가 안전하게 보관되어 있는가?
- [ ] 로그 파일이 안전하게 관리되어 있는가?
## 🚨 보안 사고 대응
### 사고 대응 절차
1. **즉시 조치**: 의심스러운 접근 차단
2. **영향 평가**: 피해 범위 확인
3. **복구 작업**: 시스템 정상화
4. **사후 분석**: 원인 분석 및 재발 방지
### 비상 연락처
- **시스템 관리자**: [연락처]
- **보안 담당자**: [연락처]
- **시놀로지 지원**: [연락처]
이 보안 가이드를 통해 안전하고 편리한 Todo 시스템을 구축할 수 있습니다.