일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- springsecurity
- OptimisticLock
- java
- S3
- ObjectOptimisticLockingFailureException
- spring DI
- Spring Cloud Gateway
- netty
- DI
- Invalid property 'principal.username' of bean class
- 알고리즘
- 백준
- multimodule testcontainers
- @transactional
- ObjectOptimisticLockingFailureException 처리
- 소수찾기 java
- 형상관리
- RefreshToken
- jpa
- interface
- AccessToken
- 멀티모듈 테스트컨테이너
- kotest testcontainers
- aop
- redissonlock aop
- spring aop
- 우아한 테크러닝
- 낙관적 락 롤백
- TestContainers
- 낙관적 락 재시도
- Today
- Total
조급하면 모래성이 될뿐
[SpringSecurity] java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null" 본문
[SpringSecurity] java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
Pawer0223 2020. 2. 10. 13:30참조 블로그 !
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를 지정해주거나, 환경설정을 등록되어있는 방식에 맞추어 설정해주면 됨 !
'TroubleShooting' 카테고리의 다른 글
[SpringSecurity] Invalid property 'principal.username' of bean class (0) | 2020.02.19 |
---|