spring security로 프로젝트를 진행했었는데, 로그인시 개발 PC에서는 문제가 없는데, 운영서버에 적용할때 일부 사용자들이 로그인할 때 문제가 발생함.
몇가지 테스트 진행하다가 원인을 못찾아서 우선 CustomAuthenticationProvider를 추가해서 해당 회원들의 경우에 대해서 우선 몇가지 인증을 더 추가해서 로그인하게 만들어놨으나, 찝찝하다.
우선 chatgpt의 도움을 받아서 정리를 해놓았는데, 내가 확인한 부분도 있고, 아직 확인을 못한부분도 있어서 정리해놓음.
ChatGPT
BCryptPasswordEncoder를 사용하여 Spring Security로 암호화된 비밀번호 인증을 할 때, 로컬 개발 환경에서는 문제가 없지만 운영 서버에서 인증이 안 되는 경우가 발생하는 주요 원인은 다음과 같습니다:
1. BCryptPasswordEncoder 버전 차이
- 원인: 로컬과 운영 서버에서 사용 중인 BCryptPasswordEncoder의 버전이 다를 수 있습니다. Spring Security 버전에 따라 BCryptPasswordEncoder의 동작이 미묘하게 달라질 수 있는데, 특히 인코딩된 해시 문자열 포맷이 달라질 수 있습니다.
- 해결 방법: 로컬과 운영 서버에서 동일한 버전의 Spring Security 및 BCryptPasswordEncoder를 사용하고 있는지 확인하세요. 의도치 않게 서로 다른 버전이 사용되고 있다면, 동일한 버전으로 맞춰야 합니다.
2. Salt 값 및 해시 결과의 차이
- 원인: BCryptPasswordEncoder는 내부적으로 랜덤한 salt 값을 사용하여 암호화합니다. 일반적으로 동일한 비밀번호를 매번 암호화하더라도 결과가 다르게 나타납니다. 그러나 이 과정에서 운영 환경의 서버 설정이나 JVM 환경에 따라 비밀번호 해시 생성이 제대로 이루어지지 않거나, 일관성이 없을 수 있습니다.
- 해결 방법: BCryptPasswordEncoder는 비밀번호와 해시를 비교할 때 자동으로 salt를 고려하므로, salt 값을 수동으로 관리할 필요는 없습니다. 다만, 운영 환경에서 JVM 버전이나 다른 설정이 문제가 될 수 있으므로, 로컬 환경과 운영 환경이 동일한 설정을 갖추도록 확인합니다.
3. 비밀번호 저장 방식의 문제 (평문 vs 해시)
- 원인: 운영 서버의 데이터베이스에 저장된 비밀번호가 BCrypt로 암호화되지 않은 경우가 있습니다. 예를 들어, 비밀번호를 평문으로 저장했거나, 다른 방식으로 해시된 비밀번호가 저장된 경우 인증이 실패하게 됩니다.
- 해결 방법: 데이터베이스에 저장된 비밀번호가 반드시 BCryptPasswordEncoder로 암호화된 상태인지 확인하세요. 이를 위해 BCrypt로 인코딩된 비밀번호는 $2a$로 시작하는 문자열 형식을 가지므로, 저장된 비밀번호가 이 형식을 따르는지 확인해 볼 수 있습니다.
4. 환경 변수 차이
- 원인: BCryptPasswordEncoder는 인코딩 작업에 많은 리소스를 요구하는데, 운영 환경에서는 시스템 환경 변수나 보안 설정 등에서 제한을 걸어둘 가능성이 있습니다. 특히 Strength(강도) 값을 높게 설정한 경우, 인코딩이나 매칭 과정이 느려져 인증이 실패할 수 있습니다.
- 해결 방법: BCryptPasswordEncoder의 강도 인자 (constructor parameter)로 지정된 숫자가 너무 높은 경우(예: 12 이상), 이를 10 이하로 낮춰 리소스를 줄여보세요. 기본값은 보통 10입니다.
5. 운영 서버의 Charset 문제
- 원인: 운영 서버와 로컬 환경의 Charset 설정이 다를 수 있습니다. 예를 들어, 로컬에서는 UTF-8이지만 운영 서버에서는 다른 문자 인코딩을 사용할 경우, BCryptPasswordEncoder가 암호화된 문자열을 다르게 해석할 수 있습니다.
- 해결 방법: 서버에서 JVM의 문자 인코딩 설정을 로컬 환경과 동일하게 설정하세요 (-Dfile.encoding=UTF-8).
6. 데이터베이스의 마이그레이션 문제
- 원인: 로컬에서 암호화된 비밀번호를 데이터베이스에 저장한 후 운영 서버로 마이그레이션할 때, 인코딩 과정에서 데이터가 잘못되었거나 일부가 손실될 수 있습니다. 예를 들어, 운영 서버로 데이터를 옮기는 과정에서 인코딩 설정이 달라지거나 데이터가 손상될 수 있습니다.
- 해결 방법: 데이터베이스 마이그레이션 시 모든 비밀번호 필드가 올바르게 이동되었는지, 인코딩 오류 없이 저장되었는지 검토합니다.
7. 서버 간의 JVM 환경 차이
- 원인: BCryptPasswordEncoder의 동작은 JVM의 특정 설정에 영향을 받을 수 있습니다. 예를 들어 운영 서버의 JVM이 로컬과 다른 버전을 사용하거나, 특정 보안 패치로 인해 동작이 달라질 수 있습니다.
- 해결 방법: 운영 서버와 로컬 개발 환경의 JVM 버전을 일치시키고, 동일한 JVM 옵션을 사용하는 것이 좋습니다.
문제 해결을 위한 점검 체크리스트
- Spring Security 버전을 운영 서버와 로컬이 동일하게 사용하고 있는지 확인합니다.
- 데이터베이스의 비밀번호 필드가 BCrypt로 인코딩된 문자열인지 확인합니다.
- Charset 설정이 로컬 환경과 운영 환경에서 동일한지 확인합니다.
- BCryptPasswordEncoder의 강도 인자가 지나치게 높지 않은지 확인합니다.
- JVM 환경 (버전, 옵션 등)이 일치하는지 점검합니다.
이렇게 각 부분을 하나씩 점검해 보면 원인을 파악할 수 있을 것입니다.