유저의 비밀번호 변경 기능을 구현하던 중, 암호화와 관련된 오류의 원인과 해결 과정을 기록하려고 한다.
우선 리액트에서 axios로 유저의 아이디,기존 비밀번호,변경할 비밀번호를 전달 받은 후 유저 테이블에 저장된 비밀번호와 입력받은 비밀번호를 비교해 일치할 경우, 변경할 비밀번호로 업데이트하려고 계획을 세웠다.
여기서 주의해야 할 점은 비밀번호가 테이블에 저장될 때 BCryptPasswordEncoder로 암호화되었기 때문에 유저가 전달한 기존 비밀번호를 그냥 비교하는 것이 아니라 BCryptPasswordEncoder를 이용해 암호화해야 한다는 것이었다.
위처럼 메소드를 만들어 호출했더니 비밀번호 불일치가 콘솔에 찍혔다.
사용자가 전달한 기존 비밀번호 값이 암호화되어 저장되었으니 비교할 때도 암호화 한 후 '==' 연산자를 이용하면 되지 않을까? 생각했는데 계속 불일치하였고, 콘솔 창에 비교값을 찍어본 후 원인을 찾을 수 있었다.
원인
여러 번 메소드를 호출하여 콘솔 창을 확인해봤더니 '입력받고 암호화한 비밀번호'인 encodedPassword의 값이 호출할 때마다 다른 값으로 암호화되는 것을 알아낼 수 있었다. 그러니까 BCryptPasswordEncoder를 사용하여 비밀번호를 암호화할 때, 같은 입력값에 대해서 매번 다른 암호화된 결과가 생성된다는 것이다. 테이블에 저장된 기존 비밀번호는 암호화한 후 바로 저장된 값이기 때문에 고정되어있지만 입력받은 비밀번호는 매번 다르게 암호화되기 때문에 서로 일치할 수가 없는 것이다. 결론적으로 BCryptPasswordEncoder로 암호화된 값을 비교하려면 '==' 연산자가 아니라 encoder.mathces() 함수를 사용해야 올바르게 비교할 수 있다.
해결
'==' 연산자를 통한 비교가 아닌 encoder.mathces() 함수로 입력받은 비밀번호와 기존 비밀번호를 바로 비교하면 올바르게 비교한 후 일치/불일치 여부를 정상적으로 반환한다.
BCryptPasswordEncoder를 사용하여 비밀번호와 같이 암호화가 필요한 데이터들을 비교할 땐 encoder.matches()를 사용해야 한다는 것을 꼭 기억해두자.
댓글