Java/Spring Boot
[Spring Boot] Spring Security 설정 커스터마이징
hh_lin
2022. 5. 1. 23:20
1. 웹 시큐리티 설정
- 아래와 같은 화면에서 My에만 인증이 필요하게 변경하고 싶은 경우
- WebSecurityConfigurerAdapter를 상속받는 Config 파일 생성
-> 이렇게 되면 Spring Boot가 제공하는 Security 자동설정은 적용되지 않음
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/", "/hello").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
}
-> 루트와 /hello에 대해서만 전부 허용하고 나머지 모든 요청은 인증 필요
-> form 인증과 basic 인증 사용
2. UserDetailsService 구현
- 보통 유저 정보를 관리하는 서비스 계층에다 UserDetailsService 인터페이스를 구현
- 이 타입의 빈이 등록되어 있으면 Spring Boot가 만들어주는 기본 사용자가 생성되지 않음
- 로그인 시 UserDetailsService가 가지고 있는 loadUserByUsername() 메소드 호출됨
@Service
public class AccountService implements UserDetailsService {
@Autowired
private AccountRepository accountRepository;
public Account createAccount(String username, String password) {
Account account = new Account();
account.setUsername(username);
account.setPassword(password);
return accountRepository.save(account);
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Account> byUsername = accountRepository.findByUsername(username);
// byUsername에 데이터가 없으면 exception, 있으면 account에 저장
Account account = byUsername.orElseThrow(() -> new UsernameNotFoundException(username));
// UserDetails는 서비스에 구현되어있는 유저 정보들의 인터페이스
// 인터페이스의 기본 구현체를 spring security가 User라는 이름으로 제공
// ROLE_USER라는 권한을 가진 account 정보를 UserDetails로 변환
return new User(account.getUsername(), account.getPassword(), authorities());
}
private Collection<? extends GrantedAuthority> authorities() {
return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
}
}
3. PasswordEncoder 설정 및 사용
@Component
public class AccountRunner implements ApplicationRunner {
@Autowired
AccountService accountService;
@Override
public void run(ApplicationArguments args) throws Exception {
Account hhlin = accountService.createAccount("hhlin", "1234");
System.out.println(hhlin.getUsername() + " password: " + hhlin.getPassword());
}
}
유저 정보 생성 후 실행해도 My 접근 시 오류 발생
-> java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
NoOpPasswordEncoder를 사용해서 PasswordEncoder를 빈으로 등록하면
My에 접근은 가능하지만 인코딩을 사용하지 않는 가장 안좋은 방법 (절대 사용하지 말 것)
-> PasswordEncoderFactories.createDelegatingPasswordEncoder() 사용할 것
@Bean
public PasswordEncoder passwordEncoder() {
// return NoOpPasswordEncoder.getInstance();
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
Service에서 PasswordEncoder를 주입받고, password를 인코딩해서 저장
@Service
public class AccountService implements UserDetailsService {
@Autowired
private AccountRepository accountRepository;
@Autowired
private PasswordEncoder passwordEncoder;
public Account createAccount(String username, String password) {
Account account = new Account();
account.setUsername(username);
account.setPassword(passwordEncoder.encode(password));
return accountRepository.save(account);
}
}
어플리케이션 실행 시 bcrypt로 인코딩된 것 확인 가능
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8/dashboard
스프링 부트 개념과 활용 - 인프런 | 강의
스프링 부트의 원리 및 여러 기능을 코딩을 통해 쉽게 이해하고 보다 적극적으로 사용할 수 있는 방법을 학습합니다., - 강의 소개 | 인프런...
www.inflearn.com