개발/일지

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

Zziny 2023. 2. 20. 04:05

SpringSecurity를 적용하기위해서,

USER 테이블에 ID : test, PASSWORD : 1234 저장하고 로그인을 시도하였더니, 해당 error가 발생하였다.

 

원인

SpringSecurity가 로그인 과정에서 어떤 Encoder를 쓸지는 database에 저장된 password의 prefix { Encoder명 }를 보고 결정 하는데 db에 저장할 때 password를 encode하지 않고 저장함.

-> SpringSecurity가 prefix를 보고 Enocder형식을 정해야 하는데, prefix가 설정 되어 있지 않아서 에러가 난 것

 

해결

PasswordEncoderFactories.createDelegatingPasswordEncoder() 사용

-> createDelegatingPasswordEncoder() 메서드 들어가 보면

-> 기본으로 BCryptPasswordEncoder 사용하는 것을 알 수 있음

@Bean
public PasswordEncoder passwordEncoder() {
    return PasswordEncoderFactories.createDelegatingPasswordEncoder(); // PasswordEncode로 BCryptPasswordEncoder 사용
}
public static PasswordEncoder createDelegatingPasswordEncoder() {
   String encodingId = "bcrypt";
   Map<String, PasswordEncoder> encoders = new HashMap<>();
   encoders.put(encodingId, new BCryptPasswordEncoder());
   encoders.put("ldap", new org.springframework.security.crypto.password.LdapShaPasswordEncoder());
   encoders.put("MD4", new org.springframework.security.crypto.password.Md4PasswordEncoder());
   encoders.put("MD5", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5"));
   encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance());
   encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
   encoders.put("scrypt", new SCryptPasswordEncoder());
   encoders.put("SHA-1", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1"));
   encoders.put("SHA-256",
         new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256"));
   encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder());
   encoders.put("argon2", new Argon2PasswordEncoder());
   return new DelegatingPasswordEncoder(encodingId, encoders);
}

회원가입 시 password를 encode해서 DB에 저장했다.

import com.numble.bankingserver.user.domain.User;
import com.numble.bankingserver.user.dto.JoinDTO;
import com.numble.bankingserver.user.repository.UserRepository;
import javax.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
@Transactional
public class UserService {

    private final UserRepository repository;
    private final PasswordEncoder passwordEncoder;

    public void joinUser(JoinDTO joinDTO) throws Exception {
        if (repository.findByUserId(joinDTO.getId()).isPresent()) {
            throw new Exception("이미 존재하는 아이디입니다.");
        }

        User user = User.createUser(joinDTO);

        user.passwordEncode(passwordEncoder);
        repository.save(user);
    }
}

 

참고

https://taesan94.tistory.com/119

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