Web Security 커스터마이징
- WebSecurityConfigurerAdapter를 상속하던 SpringBootWebSecurityConfiguration 대체
- 모든 HTTP요청에 인증을 요구하던 스프링 부트의 자동설정 해제
- WebSecurityConfigurerAdapter를 implements하는 @Configuration class 생성
- 스프링 부트의 SpringBootWebSecurityConfiguration이 빈으로 등록되지 않게 된다.
- HttpSecurity 객체를 파라미터로 받는 configure 메소드 오버라이드
- authroizeRequest() : http요청을 위한 웹 기반 보안을 설정하겠다는 의미
- antMatchers() : ant pattern으로 URL지정
- permitAll() : 해당 URL에 모든 사용자 접근을 허용
- authenticated() : 해당 URL에 인증된 사용자 접근만을 허용
- and() / formLogin() / httpBasic()으로 어떤 인증을 사용할지 설정
@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();
}
}
UserDetailsService 커스터마이징
- 유저, 패스워드를 자동으로 만들어주던 스프링 부트의 자동설정 해제
- 입력한 유저이름과 일치하는 유저 정보를 DB에서 찾아 반환하는 역할
- h2 및 spring-boot-starter-data-jpa 의존성 추가
- 유저 객체 생성을 위해, Account class 및 AccountRepository interface 추가
- 유저 객체 생성 작업을 하는 Account service 추가
- 해당 서비스 클래스에 UserDetailsService Interface를 implements
- 이를 구현하는 빈이 있어야 부트의 자동설정이 해제된다.
- pubic UserDetails loadUserByUserName(String username) 메소드를 오버라이드해야 한다.
- 로그인을 시도하면, 해당 메소드가 호출 → 입력한 유저이름에 해당하는 정보를 담아 객체로 반환
@Entity
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
loadUserByUserName 오버라이딩
- Optional 객체를 사용해보자.
- DB에서 입력받은 username과 일치하는 유저 정보를 찾았다면, 이 정보로 User객체를 생성하여 반환
- 해당 메소드는 UserDetails라는 인터페이스의 구현체를 반환해야하는데 시큐리티가 제공.
→ User(유저정보의 name, 유저정보의 password, 보유권한을 담은 ArrayList) - 보유 권한 ArrayList는 authorities 메소드로 만든다.
public interface AccountRepository extends JpaRepository<Account, Long> {
Optional<Account> findByUsername(String username);
}
@Service
public class AccountService implements UserDetailsService{
private AccountRepository accountRepository;
public AccountService(AccountRepository accountRepository){
this.accountRepository = accountRepository;
}
public Account createAccount(String username, String password){
Account account = new Account(username, password);
return this.accountRepository.save(account);
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Account> byUsername = accountRepository.findByUsername(username);
Account account = byUsername.orElseThrow(() -> new UsernameNotFoundException(username));
return new User(account.getUsername(), account.getPassword(), authorites());
}
private Collection<? extends GrantedAuthority> authorites(){
return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
}
}
UserDetailsService 커스터마이징
- 패스워드는 DB에 암호화되어 저장되어야 한다.
- 암호화를 위한 패스워드 인코더 필요
- WebConfig에 패스워드 인코더를 빈으로 등록
→ PasswordEncoderFactories class의 createDelegatingPasswordEncoder() 메소드 사용 - UserDetailsService를 impl한 서비스 클래스에서 해당 인코더를 주입받는다
- 해당 인코더로 인코딩해서 엔티티 객체에 저장해야 한다.
//WebConfig에서 등록한 인코더를 주입받아야 한다.
//loadUserByUsername 메소드에서 User객체를 반환할 때 인코딩
return new User(account.getUsername(), passwordEncoder.encode(account.getPassword()), authorites());
'학습 > Spring' 카테고리의 다른 글
[spring] 스프링 부트에서 @WebMvcTest 사용하며 RestTemplate 주입받기 (0) | 2020.06.11 |
---|---|
[spring] 스프링 부트에서 REST Client 이용하기 (0) | 2020.05.23 |
[spring] 스프링 부트에서 Spring Security 사용하기 (0) | 2020.05.19 |
[spring] 스프링 부트에서 Redis 사용하기 (0) | 2020.05.18 |
[spring] 데이터베이스 초기화 및 마이그레이션 (0) | 2020.05.17 |
댓글