--- description: globs: alwaysApply: true --- # 보안 가이드 ## 인증 및 인가 ### 세션 기반 인증 현재 시스템은 세션 기반 인증을 사용합니다: ```java // 사용자 인증 정보 저장 PersonBean person = new PersonBean(); person.setUserId(userId); person.setUserName(userName); request.getSession().setAttribute(Constants.PERSON_BEAN, person); // 인증 정보 조회 PersonBean person = (PersonBean)request.getSession().getAttribute(Constants.PERSON_BEAN); if (person == null) { // 로그인 페이지로 리다이렉트 } ``` ### 권한 관리 구조 - **AUTH_GROUP**: 권한 그룹 정의 - **MENU_AUTH_GROUP**: 메뉴별 권한 그룹 매핑 - **USER_AUTH**: 사용자별 권한 할당 ### 메뉴 접근 권한 체크 ```java public HashMap checkUserMenuAuth(HttpServletRequest request, Map paramMap) { PersonBean person = (PersonBean)request.getSession().getAttribute(Constants.PERSON_BEAN); String userId = person.getUserId(); paramMap.put("userId", userId); paramMap.put("menuUrl", request.getRequestURI()); // 권한 체크 쿼리 실행 return sqlSession.selectOne("admin.checkUserMenuAuth", paramMap); } ``` ## 데이터 보안 ### SQL 인젝션 방지 **올바른 방법** - 파라미터 바인딩 사용: ```xml ``` **위험한 방법** - 직접 문자열 치환: ```xml ``` ### 패스워드 보안 ```java // 패스워드 암호화 (EncryptUtil 사용) String encryptedPassword = EncryptUtil.encrypt(plainPassword); // 패스워드 검증 boolean isValid = EncryptUtil.matches(plainPassword, encryptedPassword); ``` ### 입력값 검증 ```java // CommonUtils를 사용한 입력값 정제 String safeInput = CommonUtils.checkNull(request.getParameter("input")); if (StringUtils.isEmpty(safeInput)) { throw new IllegalArgumentException("필수 입력값이 누락되었습니다."); } ``` ## 세션 보안 ### 세션 설정 [web.xml](mdc:WebContent/WEB-INF/web.xml)에서 세션 타임아웃 설정: ```xml 1440 ``` ### 세션 무효화 ```java // 로그아웃 시 세션 무효화 @RequestMapping("/logout.do") public String logout(HttpServletRequest request) { HttpSession session = request.getSession(false); if (session != null) { session.invalidate(); } return "redirect:/login.do"; } ``` ## 파일 업로드 보안 ### 파일 확장자 검증 ```java public boolean isAllowedFileType(String fileName) { String[] allowedExtensions = {".jpg", ".jpeg", ".png", ".gif", ".pdf", ".doc", ".docx", ".xls", ".xlsx"}; String extension = fileName.toLowerCase().substring(fileName.lastIndexOf(".")); return Arrays.asList(allowedExtensions).contains(extension); } ``` ### 파일 크기 제한 ```java // web.xml에서 파일 업로드 크기 제한 10485760 52428800 ``` ### 안전한 파일명 생성 ```java // FileRenameClass 사용하여 안전한 파일명 생성 String safeFileName = FileRenameClass.rename(originalFileName); ``` ## XSS 방지 ### 출력값 이스케이프 JSP에서 사용자 입력값 출력 시: ```jsp ${userInput} ``` ### JavaScript에서 데이터 처리 ```javascript // 안전한 방법 var safeData = $('
').text(userInput).html(); // 위험한 방법 var dangerousData = userInput; // XSS 공격 가능 ``` ## CSRF 방지 ### 토큰 기반 CSRF 방지 ```jsp
``` ```java // 컨트롤러에서 CSRF 토큰 검증 @RequestMapping("/save.do") public String save(HttpServletRequest request, @RequestParam Map paramMap) { String sessionToken = (String)request.getSession().getAttribute("csrfToken"); String requestToken = (String)paramMap.get("csrfToken"); if (!sessionToken.equals(requestToken)) { throw new SecurityException("CSRF 토큰이 일치하지 않습니다."); } // 정상 처리 } ``` ## 로깅 및 감사 ### 보안 이벤트 로깅 ```java private static final Logger securityLogger = LoggerFactory.getLogger("SECURITY"); public void logSecurityEvent(String event, String userId, String details) { securityLogger.info("Security Event: {} | User: {} | Details: {}", event, userId, details); } // 사용 예시 logSecurityEvent("LOGIN_SUCCESS", userId, request.getRemoteAddr()); logSecurityEvent("ACCESS_DENIED", userId, request.getRequestURI()); ``` ### 민감 정보 마스킹 ```java public String maskSensitiveData(String data) { if (data == null || data.length() < 4) { return "****"; } return data.substring(0, 2) + "****" + data.substring(data.length() - 2); } ``` ## 환경별 보안 설정 ### 개발 환경 - 상세한 오류 메시지 표시 - 디버그 모드 활성화 - 보안 제약 완화 ### 운영 환경 - 일반적인 오류 메시지만 표시 - 디버그 모드 비활성화 - 엄격한 보안 정책 적용 ```java // 환경별 설정 예시 if (Constants.IS_PRODUCTION) { // 운영 환경 설정 response.sendError(HttpServletResponse.SC_FORBIDDEN, "접근이 거부되었습니다."); } else { // 개발 환경 설정 response.sendError(HttpServletResponse.SC_FORBIDDEN, "권한 부족: " + detailedMessage); } ``` ## 보안 체크리스트 ### 코드 레벨 - [ ] SQL 인젝션 방지 (#{} 파라미터 바인딩 사용) - [ ] XSS 방지 (출력값 이스케이프) - [ ] CSRF 방지 (토큰 검증) - [ ] 입력값 검증 및 정제 - [ ] 패스워드 암호화 저장 ### 설정 레벨 - [ ] 세션 타임아웃 설정 - [ ] 파일 업로드 제한 - [ ] 오류 페이지 설정 - [ ] HTTPS 사용 (운영 환경) - [ ] 보안 헤더 설정 ### 운영 레벨 - [ ] 정기적인 보안 점검 - [ ] 로그 모니터링 - [ ] 권한 정기 검토 - [ ] 패스워드 정책 적용 - [ ] 백업 데이터 암호화