📝느낀 점
비밀번호와 같은 민감한 데이터를 처리할 때는 반드시 안전하게 관리해야 한다는 점을 알게 되었습니다. 임시 비밀번호를 해싱하지 않고 저장하는 실수를 수정함으로써 데이터 보안을 강화할 수 있었습니다. 이를 통해 보안의 중요성을 다시 한 번 인식하게 되었고, 작은 실수가 큰 문제로 이어질 수 있다는 것을 알게 되었습니다. 또한, 서버에서 보안을 유지하기 위한 코드 리뷰와 테스트의 중요성을 배웠습니다. 지속적인 코드와 시스템 개선의 필요성을 느꼈습니다. 보안이 강화된 시스템은 사용자 신뢰도를 높일 수 있고, 개인정보 유출 사고를 예방할 수 있음을 깨달았습니다. 이번 경험을 바탕으로 앞으로 더 나은 보안 관행을 선택하는 데 큰 도움이 될 것이라고 생각합니다.
어떻게 했기에 문제 상황을 마주하게 되었는지
Spring Boot와 JPA를 사용하여 비밀번호 찾기 기능을 구현했습니다.
이 기능은 사용자가 이메일로 임시 비밀번호를 발급받고 이를 통해 로그인할 수 있도록 설계되었습니다.
구현 단계에서 비밀번호 발급 및 이메일 전송은 정상적으로 작동하였으나,
실제 사용자 테스트 과정에서 발급된 임시 비밀번호로 로그인이 되지 않는 문제를 발견했습니다.
로그인을 시도할 때마다 "아이디 혹은 비밀번호가 일치하지 않습니다"라는 오류 메시지가 발생하여 문제를 감지했습니다.
이게 왜 문제인지
비밀번호 찾기 기능은 사용자가 계정에 접근할 수 있도록 하는 중요한 보안 기능이라고 생각합니다.
이 기능이 제대로 작동하지 않으면 사용자는 자신의 계정에 접근할 수 없게 되어 큰 불편을 겪게 됩니다.
또한, 임시 비밀번호가 해싱되지 않은 상태로 저장되면, 데이터베이스가 해킹당했을 때
사용자 비밀번호가 쉽게 유출될 수 있어 심각한 보안 취약점이 됩니다.
따라서 이 문제는 사용자 데이터 보안 측면에서 매우 중요하게 다뤄져야 한다고 생각하기에, 문제라고 생각했습니다.
문제를 어떻게 감지했는지
비밀번호 찾기 기능을 구현한 후 테스트 단계에서 문제를 발견하게 되었습니다.
테스트 과정에서 여러 단계를 거치며 문제를 감지할 수 있었습니다.
먼저, 사용자 계정으로 이메일을 통해 임시 비밀번호를 발급받고,
해당 비밀번호로 로그인을 시도했으나 "아이디 혹은 비밀번호가 일치하지 않습니다"라는 오류 메시지가 나타났습니다.
이 문제를 해결하기 위해 Spring Boot 애플리케이션의 서버 로그를 확인하여
로그인 시도 시 발생한 예외와 에러 메시지를 분석했습니다.
로그를 분석한 결과, 데이터베이스에서 비밀번호 검증 단계에서 문제가 발생하고 있다는 것을 확인할 수 있었습니다.
이후, 문제의 원인을 더 명확히 파악하기 위해 MemberService 클래스와
MemberRepository 클래스의 코드를 검토했습니다.
이 과정에서 임시 비밀번호를 데이터베이스에 저장하는 과정에서 해싱이 누락된 것을 발견하게 되었습니다.
이러한 과정을 통해 문제의 원인을 명확히 이해하게 되었고, 구체적인 해결책을 생각할 수 있었습니다.
어떻게 해결했는지
MemberService 클래스의 updatePassword 메서드에서 임시 비밀번호를 데이터베이스에 업데이트할 때, passwordEncoder를 사용하여 해싱하지 않았습니다.
이를 수정하여 임시 비밀번호를 해싱한 후 저장하도록 했습니다.
@Transactional
public void updatePassword(String str, String userEmail) {
String pw = passwordEncoder.encode(str);
Optional<Member> member = memberRepository.findByEmail(userEmail);
if (member.isPresent()) {
Long id = member.get().getId();
memberRepository.updatePasswordById(id, pw);
}
}
또한, 비밀번호 검증 로직을 개선하여 코드의 가독성과 유지보수성을 높였습니다.
public Optional<Member> loginMember(String name, String password) {
Optional<Member> member = memberRepository.findByName(name);
if (member.isPresent() && passwordEncoder.matches(password, member.get().getPassword())) {
return member;
}
return Optional.empty();
}
컨트롤러에서의 중복 매핑 문제를 해결하기 위해 MemberController 클래스의 login 메서드를 수정했습니다.
@PostMapping("/login")
public String login(MemberLoginRequestDTO memberLoginRequestDTO, Model model) {
Optional<Member> member = memberService.loginMember(memberLoginRequestDTO.getName(), memberLoginRequestDTO.getPassword());
if (member.isPresent()) {
model.addAttribute("memberName", member.get().getName());
return "/members/login";
} else {
model.addAttribute("loginMessage", "아이디 혹은 비밀번호가 일치하지 않습니다.");
return "/home";
}
}
그렇게 하면 왜 해결되는지
비밀번호를 해싱하여 데이터베이스에 저장함으로써 보안이 크게 강화됩니다.
해싱은 단방향 암호화 방식으로, 비밀번호가 해킹되더라도 복원이 불가능하거나
어렵게 만들어 사용자 데이터를 안전하게 보호할 수 있습니다.
특히, 데이터베이스가 침해되었을 때 비밀번호가 노출되는 위험을 크게 줄일 수 있어 필수적인 조치입니다.
또한, 비밀번호 검증 로직을 간소화한 것은 백엔드 시스템의 성능을 향상시키는 중요한 개선 사항입니다.
간소화된 로직 덕분에 코드 중복이 제거되고, 비밀번호 검증 과정이 최적화되어 로그인 처리 속도가 향상됩니다.
특히, 많은 사용자가 동시에 로그인할 때 시스템 성능을 유지하는 데 중요한 역할을 합니다.
이러한 접근 방식은 백엔드 시스템의 보안성과 성능을 동시에 개선하는 효과적인 방법입니다.
해싱된 비밀번호를 통해 데이터 유출 위험을 최소화하고,
간소화된 검증 로직을 통해 시스템의 안정성을 확보할 수 있습니다.
얼마나 개선되었는지
이 변경으로 인해 임시 비밀번호를 사용하는 로그인 기능이 정상적으로 작동하게 되었으며,
사용자들이 계정에 안전하게 접근할 수 있게 되었습니다.
보안 측면에서는 비밀번호 해싱을 통해 데이터 유출의 위험이 감소하여,
시스템의 전반적인 보안 수준이 강화 되다고 생각합니다.
또한, 간소화된 코드 구조는 새로운 기능 추가나 수정 작업을 쉽게 할 수 있도록 하여,
시스템 확장 작업에서도 시간을 절감할 수 있을 것이라고 생각합니다.
이러한 개선은 장기적으로 시스템의 안정성과 성능을 유지하는 데 도움이 될 것입니다.
배우는 것은 무엇인지
이번 작업을 통해 비밀번호와 같은 중요한 데이터를 처리할 때는
항상 해싱을 통해 보안을 강화해야 한다는 점을 배웠습니다.
또한, 코드의 가독성과 유지보수성을 위해 불필요한 반복을 제거하고
간결하게 작성하는 것이 중요하다는 것을 알게 되었습니다.
특히, 데이터베이스와의 상호작용 시 발생할 수 있는 보안 취약점을 미리 파악하고,
이를 방지하기 위한 철저한 검증 과정이 필요하다는 점을 느낄 수 있었습니다.
무엇을 얻을 것인지
비밀번호 처리 시스템을 강화함으로써 데이터 유출과 같은 보안 사고를 예방할 수 있게 되었으며,
사용자에게 보다 안전한 서비스를 제공하는 중요한 기반이 되었습니다.
사용자들이 비밀번호 찾기 기능을 통해 안전하게 계정에 접근할 수 있도록 보장 했다고 생각합니다.
그리고 백엔드 개발 측면에서는, 코드 구조를 단순화하고 가독성을 높였다고 생각합니다.
유지보수가 용이한 코드 베이스를 작성함으로써, 새로운 기능을 추가하거나
기존 기능을 수정할 때 발생할 수 있는 오류나 버그를 최소화할 수 있다고 생각합니다.
향후 시스템 규모가 커진다고 하더라도, 현재의 구조를 바탕으로 추가적인 성능 최적화나 기능 확장이 용이할 것입니다.
결과적으로, 이러한 개선은 시스템 안정성을 유지하는 데 중요한 역할을 할 것입니다.
이 방법이 최선이었는지
이 방법은 현재 상황에서 보안과 성능을 동시에 개선할 수 있는 최선의 방법 중 하나였다고 생각합니다.
비밀번호를 해싱하여 저장하고, 데이터베이스 조회 및 검증 로직을 통해 문제를 해결했습니다.
그러나 제가 아직 모르고 있는 보안 측면도 있다고 생각하기에 지속적으로 공부하며 개선해야 된다고 생각합니다.
앞으로도 새로운 보안 기법과 인증 방식을 도입하여 시스템을 지속적으로 개선해 나가겠습니다.
다른 방법은 없었는지
다른 방법으로는 OAuth2와 같은 외부 인증 시스템을 도입하여 비밀번호 관리의 부담을 줄이는 것도 고려할 수 있습니다.
이러한 시스템은 사용자 인증과 권한 부여를 효율적으로 관리할 수 있으며, 보안 측면에서도 장점을 제공합니다.
또한, 비밀번호 관리 외에도 SMS 인증, 2단계 인증 등의 추가적인
보안 절차를 도입하여 보안을 강화할 수 있다고 생각합니다.
그러나 현재 상황에서는 내부적으로 비밀번호 관리를 개선하는 것이 적절한 해결책이었습니다.
'프로젝트(project)' 카테고리의 다른 글
비밀번호 검증 및 데이터 무결성 유지 (0) | 2024.07.25 |
---|---|
비밀번호 해싱과 Security로 보안 높이기 (0) | 2024.07.25 |
트랜잭션 및 외래키 제약 조건 문제 (0) | 2024.07.24 |
NonUniqueResultException 해결하기 (0) | 2024.07.24 |
MySQL과 S3를 활용한 효율적인 설계 (0) | 2024.07.23 |