[2023.09.14] There is no PasswordEncoder mapped for the id "null" 오류

아스라이지새는달·2023년 10월 30일
2
post-thumbnail

Spring Security와 JWT를 통해 로그인 기능을 구현하고 테스트하는 과정에서 java.lang.IllegalArgumentException:There is no PasswordEncoder mapped for the id "null" 라는 에러를 맞닥뜨렸다. 해당 에러가 왜 발생하였는지, 어떻게 해결하였는지 정리하기 위해 본 포스트를 작성하였다.

❓ 어떤 문제점인가?

Postman을 통해 로그인 테스트를 하는 도중 500 Internal Server Error가 발생하였다.

IntelliJ를 확인해보니 log에 java.lang.IllegalArgumentException:There is no PasswordEncoder mapped for the id "null"가 찍혀있었다.


👨🏻‍💻 왜 이런 에러가?

아직 멤버 추가 API를 개발하지 않아 DB에 멤버 데이터를 직접 넣은 것이 화근이었다.

17, 18번 데이터는 추후 멤버 추가 API를 개발한 후 해당 API를 통해 DB에 넣은 데이터이다.

자세한 원인은 Spring Security 5 이상부터 PasswordEncoder를 통해 password를 처리하는데 DB에 있는 password 데이터가 PasswordEncoder가 처리하는 형식으로 되어있지 않아서 발생한 것이다.

PasswordEncoderFactories.createDelegatingPasswordEncoder()로 생성한 PasswordEncoder는 BCryptPasswordEncoder가 사용되며 prefix인 {id}로 사용할 PasswordEncoder 종류가 정해진다. Default는 bcrypt이다. 즉, 로그인 과정에서 어떤 Encoder를 사용할지 DB에 저장된 password의 prefix {id}를 보고 결정한다.

허나 DB에 직접 넣은 19번 데이터는 prefix가 정해지지 않았고 로그인하는 과정 passwordEncoder.matches(rawPassword, encodePassword)에서 prefix가 없는 password에 mapping되는 Encoder가 없기 때문에 오류가 발생하였다.


🔨 그렇다면 해결책은?

크게 2가지가 있다.

  1. Spring Security 5 이전에 사용되던 NoOpPasswordEncoder를 사용하는 방법
    정상적으로 응답이 넘어온다. 하지만 이 방법은 deprecated 되었기 때문에 지양하는 방법이다. 실제로 해당 방법을 사용하면 IntelliJ에서 uses or overrides a deprecated API.라는 warning이 뜨는 것을 확인할 수 있다.

  2. DB에 데이터를 저장할 때 prefix를 붙여주는 방법
    prefix로 {noop}을 붙여서 저장해준다.
    마찬가지로 정상적으로 응답이 넘어오는 것을 확인할 수 있다.

멤버를 추가할 때 password를 인코딩하여 저장하는 API를 작성하는 것이 가장 좋은 방법이지만 필자는 이 테스트를 진행하는 시점에 해당 API를 작성하지 않아 2번 방법으로 테스트를 진행하였다.


💡 의문점

문득 PasswordEncoderFactories.createDelegatingPasswordEncoder()의 default prefix가 {bcrypt}라면 DB에 직접 저장할 때 {bcrypt}를 붙여서 저장하면 되지 않을까라는 의문점이 생겼다. 그래서 이 경우도 테스트 해보았다.

DB에 {bcrypt}를 붙여서 직접 넣어봤다.

Postman에서 로그인 요청을 보내봤는데 401 HTTP Status Code가 응답되었다.

IntelliJ를 확인해보니 Encoded password does not look like BCrypt라는 warning이 뜬 것을 확인할 수 있었다.

결론적으로 prefix는 bcrypt이기 때문에 BCryptPasswordEncoder를 사용하지만 password가 bcrypt 형식으로 인코딩되지 않았기 때문에 해당 오류가 뜨는 것이다.


🔍 Reference

https://ddasi-live.tistory.com/80

https://java.ihoney.pe.kr/498

https://taesan94.tistory.com/119

https://csksoft.tistory.com/83

profile
웹 백엔드 개발자가 되는 그날까지

0개의 댓글