조급하면 모래성이 될뿐

[SpringSecurity] java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null" 본문

TroubleShooting

[SpringSecurity] java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

Pawer0223 2020. 2. 10. 13:30

참조 블로그 !

 

[ 참조링크 1 ]

[ 허니몬(Honeymon)의 자바guru ]

[ 참조링크 3 ]

 

 

 

SpringSecurity를 적용하기위해서, 계정테이블에 ID : TEST, PW : 1234의 데이터를 직접 INSERT하였다.

 

이후에 로그인 form에서 로그인을 시도하였더니, 해당 error가 발생하였다.

 

원인은 SpringSecurity 5버전 이상부터는 PasswordEncoder를 처리를 하는데, 이때 PasswordEncoder를 처리하기위한 형식으로 pw가 저장되어있지 않기때문이다. ( 자세한 설명 : [ 허니몬님의 자바guru ] )

 

정리하면, 과거에는 스프링 시큐리티에서 제공하는 PasswordEncorder가 사용자가 등록한 비밀번호를 단방향으로 변환하여 저장하는 용도로 사용되었다.

 

그리고 시대적인 흐름에 따라서 이 알고리즘을 점점 고도화해야되는데.. ( 계속뚫리니깐.. )

이런 과정에서 서비스에 저장된 비밀번호에 대한 암호화 알고리즘을 변경하는 일은 상당히 번거롭다. ( 어렵다. )

 

그것을 해결하기위해 스프링시큐리티에서 내놓은 해결책이 DelegatingPasswordEncoder다.

 

간단하게 코드를 사용해보면.. 

public class PassWordEncoderTest {

	private static PasswordEncoder passwordEncoder;
    
	private static void encode() {

		// 이렇게쓰면 기본으로 bcrypt형식으로 암호화 되는구나..
		passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();

		String password = "password";
		String encPassword = passwordEncoder.encode(password);

		System.out.println(" password : " + password );
		System.out.println(" encPassword : " + encPassword ); // encode의 결과로 앞에 저절로 {bcrypt}가 붙어왔네 ??

		System.out.println("1. passwordEncoder.matches(password, encPassword); : " + passwordEncoder.matches(password, encPassword));
		System.out.println("2. (encPassword).contains(\"{bcrypt}\") : " + (encPassword).contains("{bcrypt}"));

	}
}

 

- PasswordEncoderFactories.createDelegatingPasswordEncoder()로 생성한 PasswordEncode는 BCryptPasswordEncoder가 사용되며 앞에 {id}로 PasswordEncoder 유형이 정의된다.

- 기본이 bcrypt이다.
- 정리하면, SpringSecurity가 로그인 과정에서 어떤 Encoder를 쓸지는 database에 저장된 password의 prefix { Encoder명 }를 보고 결정한다.

- 우리는 따로 설정을하지않았으니, SpringSecurity가 prefix를 보고 Enocder형식을 정해야 하는데, 이것조처 설정이 되어있지 않아서 에러가 난것이다.

 

해결해주기위한 방법은 크게2가지다.

 

1. db의 pw앞에 prefix를 붙여서 저장한다.

AS-IS TO-BE
1234

- {noop}1234

- {bcrypt}1234

1) {noop}1234

결과 : 로그인 URL이동

2) {bcrypt}1234

결과 : 증명실패

 

2. Encoder설정을 해준다.

 

비밀번호 1234로다시 바꿔놓고..

 

SecurityConfig클래스파일에 PasswordEncoder설정 추가.

 

2-1) noOpPasswordEncoder

	@Bean
	public PasswordEncoder noOpPasswordEncoder(){
		return NoOpPasswordEncoder.getInstance();
	}

결과 : 성공 !

 

2-2) noOpPasswordEncodercreateDelegatingPasswordEncoder

	  @Bean
	  public static PasswordEncoder passwordEncoder() {
	    return PasswordEncoderFactories.createDelegatingPasswordEncoder();
	  }

 

- 서버재기동하고..

 

- 돌려보면, error..id 머시기하는데.. id를못찾는단소리겟지..?

- pw를 {bcrypt}1234로 id지정해주도록 바꾸고 다시 로그인 하면..

- 저 에러는 사라지지만 ! 증명실패 에러가 난다 !

결론 :

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

 

SpringSecurity사용해서 로그인할 때 위와같은 에러가난다면, pw데이터에 인코딩 id를 지정해주거나, 환경설정을 등록되어있는 방식에 맞추어 설정해주면 됨 !

반응형