ERP-node/.cursor/rules/security-guide.mdc

127 lines
2.6 KiB
Plaintext
Raw Normal View History

2025-08-21 09:41:46 +09:00
---
description:
globs:
2025-08-21 09:41:46 +09:00
alwaysApply: true
---
2025-08-21 09:41:46 +09:00
# 보안 가이드
## 인증 및 인가
### JWT 기반 인증
현재 시스템은 JWT 토큰 기반 인증을 사용합니다:
2025-08-21 09:41:46 +09:00
```typescript
// 토큰 생성 (로그인 시)
const token = jwt.sign(
{ userId, companyCode, role },
process.env.JWT_SECRET,
{ expiresIn: process.env.JWT_EXPIRES_IN || '24h' }
);
2025-08-21 09:41:46 +09:00
// 토큰 검증 (미들웨어)
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
2025-08-21 09:41:46 +09:00
```
### 권한 관리 구조
- **auth_group**: 권한 그룹 정의
- **menu_auth_group**: 메뉴별 권한 그룹 매핑
- **user_auth**: 사용자별 권한 할당
### 인증 미들웨어
`backend-node/src/middleware/authMiddleware.ts` 참조
2025-08-21 09:41:46 +09:00
## 데이터 보안
### SQL 인젝션 방지
**올바른 방법** - 파라미터 바인딩 사용:
```typescript
const result = await pool.query(
'SELECT * FROM user_info WHERE user_id = $1',
[userId]
);
2025-08-21 09:41:46 +09:00
```
**위험한 방법** - 직접 문자열 삽입:
```typescript
const result = await pool.query(
`SELECT * FROM user_info WHERE user_id = '${userId}'`
);
2025-08-21 09:41:46 +09:00
```
### 패스워드 보안
```typescript
import bcrypt from 'bcryptjs';
2025-08-21 09:41:46 +09:00
// 해싱
const hashedPassword = await bcrypt.hash(plainPassword, 10);
2025-08-21 09:41:46 +09:00
// 검증
const isValid = await bcrypt.compare(plainPassword, hashedPassword);
2025-08-21 09:41:46 +09:00
```
### 입력값 검증
```typescript
import Joi from 'joi';
2025-08-21 09:41:46 +09:00
const schema = Joi.object({
userId: Joi.string().required().max(50),
email: Joi.string().email().required(),
});
2025-08-21 09:41:46 +09:00
const { error, value } = schema.validate(req.body);
if (error) {
return res.status(400).json({ success: false, message: error.message });
2025-08-21 09:41:46 +09:00
}
```
## 보안 미들웨어
2025-08-21 09:41:46 +09:00
### Helmet (보안 헤더)
```typescript
import helmet from 'helmet';
app.use(helmet());
2025-08-21 09:41:46 +09:00
```
### Rate Limiting
```typescript
import rateLimit from 'express-rate-limit';
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
});
app.use('/api/', limiter);
2025-08-21 09:41:46 +09:00
```
### CORS 설정
```typescript
import cors from 'cors';
app.use(cors({
origin: process.env.CORS_ORIGIN,
credentials: true,
}));
2025-08-21 09:41:46 +09:00
```
## 보안 체크리스트
### 코드 레벨
- [ ] SQL 인젝션 방지 ($1 파라미터 바인딩 사용)
- [ ] XSS 방지 (React 자동 이스케이프 활용)
- [ ] 입력값 검증 (Joi 스키마)
- [ ] 패스워드 bcrypt 해싱
- [ ] JWT 토큰 만료 설정
2025-08-21 09:41:46 +09:00
### 설정 레벨
- [ ] Helmet 보안 헤더
- [ ] Rate Limiting 적용
- [ ] CORS 적절한 설정
2025-08-21 09:41:46 +09:00
- [ ] HTTPS 사용 (운영 환경)
- [ ] 환경 변수로 시크릿 관리
2025-08-21 09:41:46 +09:00
### 운영 레벨
- [ ] winston 로깅 모니터링
2025-08-21 09:41:46 +09:00
- [ ] 권한 정기 검토
- [ ] 패스워드 정책 적용
- [ ] 백업 데이터 암호화