I can do it(Feat. DEV)

Spring Security passwordEncoder 설정 관련 본문

개발자 모드/응용

Spring Security passwordEncoder 설정 관련

까짓거 해보자 개발자 2022. 10. 12. 17:08
728x90

스펙 : Spring Boot, h2 db, jsp

 

h2 db에 아래 표와 같이 관리자 데이터를 insert 후

id password
admin 123

Spring security를 사용해서 로그인 로직 구현 중

로그인을 했는데

There is no PasswordEncoder mapped for the id "null"와 같은 에러를 만났음.

 

바로 갓글에 검색.

여러 블로그를 찾아보고 종합한 결과

필자는 security 설정에 password encoding 설정을 하지 않았고,

비밀번호가 텍스트 형태라서 에러가 났음.

 

🌈해결방법

1.  db에 저장된 pw앞에 prefix를 붙여서 저장하는 것 혹은 password를 비교할 때 prefix를 붙여주는 것.
//db insert문
insert into exam_admin(id, password, name, phone)	
	values('admin', '{noop}123','관리자이름1', '010-1234-1234');

이런 식으로 저장을 하거나 

admin.setPassword("{noop}"+admin.getPassword());

 

이런 식으로 pw 비교하기 전에 admin pw를 세팅해주면 security에서 에러가 나지 않음.

 

But ❗❗

Spring Security 5 버전으로 업그레이드하면서 암호 관리 프로세스를 개편하여

일반 텍스트로 pw를 저장하는 것은 문제가 될 수 있고, 

이전 방식이기때문에 향후 미래를 봤을 때 1번 방법은 PASS.

(Spring Security 5 이전에 사용하던 NoOpPasswordEncoder 방식도 안전문제 and 사용하지 않기 때문에 PASS)

 

 

2. Security에 원하는 PasswordEncoder을 설정 후 UserDetail Service에 해싱 추가.

이부분은 다양한 PasswordEncoder 이 있기 때문에 꼭 필자와 같게 설정할 필요는 없음.

필자는 시큐리티 5 기본 전략이 bcrypt 이기도  하고 가장 많이 쓰인다는 BCryptPasswordEncoder 사용함.

//Spring Security 설정
@Bean
public PasswordEncoder passwordEncoder(){
    return new BCryptPasswordEncoder();
}

먼저 passwordEncoder Bean으로 등록함.

시큐리티에 빈만 등록  후 로그인을 진행하면

경고문 : Encoded password does not look like BCrypt

이런 로그가 찍힘.

처음엔 왜그런지 몰랐지만(🤬)

차분히 생각해보니 db에 저장된 pw는 일반 텍스트여서 그렇다는 걸 깨닫게 됨.😅

 

@Service
public class AdminDetailService implements UserDetailsService {

    @Autowired
    private AdminRepository adminRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;	//@Autowired를 통해 PasswordEncoder를 선언할 때 자동으로 클래스 바인딩 됨.

    @Override
    public UserDetails loadUserByUsername(String adminId) throws UsernameNotFoundException{
        Admin admin = adminRepository.findOneById(adminId);
        if(admin == null){
            throw new UsernameNotFoundException("해당 관리자가 없습니다.");
        }
        
        //★해싱하는 코드★
        String password = passwordEncoder.encode(admin.getPassword());

        admin.setPassword(password);

	// 밑 부분은 자유롭게 설정
        // 필자는 ExamAdmin이라는 User Class 타입을 만들어서 진행하였음.
        ExamAdmin examAdmin = new ExamAdmin(admin, buildAdminAuthority());

        return examAdmin;
    }

    private Set<GrantedAuthority> buildAdminAuthority() {	//권한 설정 부분

        Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();

        setAuths.add(new SimpleGrantedAuthority("ROLE_ADMIN"));

        return setAuths;
    }
}

위 코드처럼 해싱하는 코드를 추가하여 db에 저장된 pw를 해싱하여 진행하였음.

이후 로그인을 진행하면 문제없이 로그인이 되었음❗❗

 

Spring Security에 관해서는 매번 공부할때마다 느끼지만 참 어렵고 공부할게 많다는 것을 느낌...

그래도 이번엔 PasswordEncoder 에 대해서 많이 알게되었음. 끝.

 

다들 행복하길.

 

 

📢참조

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

 

[spring-security] 5.0 에서 달라진 암호변환정책, DelegatingPasswordEncoder

새로운 프로젝트를 시작하면서 스프링 시큐리티 5.0을 적용하고 있다. 어떤 새로운 기능이 있는지 확인하기 위해서 참고문서(What’s New in Spring Security 5.0)를 살펴봤다. 새로운 기능이 추가되었는

java.ihoney.pe.kr

https://memo-the-day.tistory.com/164

 

Spring Security 5의 기본 비밀번호 인코더

1. 개요 Spring Security 4에서는 메모리 내 인증을 사용하여 암호를 일반 텍스트로 저장할 수있었습니다. 버전 5의 암호 관리 프로세스를 대대적으로 개편하여 암호 인코딩 및 디코딩을위한보다 안

memo-the-day.tistory.com

https://mia-dahae.tistory.com/120

 

[Spring Security]BCrypt를 사용하여 패스워드 해싱하기

회원 가입 기능을 만들경우 절대 입력한 문자열을 그대로 DB에 저장하면 안된다. 보안에 매우 취약하기 때문이다. 그렇기때문에 패스워드를 해싱 하여 저장해야하는데 BCrypt가 가장 많이쓰이는

mia-dahae.tistory.com

 

728x90