시큐리티 설정
- Spring Security는 의존성만 추가해도 기본 인증 폼을 보내줍니다.(Spring boot 사용시 자동으로 auto config 되는 부분이 있음) ==> 자동 설정으로 id 가 user 이고 password 가 콘솔에 출력되는 유저를 생성합니다.
-
Spring security 기본 설정 추가
<!-- pom.xml --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
// java 설정파일
// 시큐리티 설정 파일임을 나타냄
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 특정 요청에 대해 설정
// 인가(요청에 대한 권한 설정)
http.authorizeRequests()
.mvcMatchers("/", "/info").permitAll() // 인증없이 접근 가능
.mvcMatchers("/admin").hasRole("ADMIN") // role 에 따라 구분
.anyRequest().authenticated(); // 기타 요청은 인증을 하기만 하면 됨
// 인증(login 방식 설정)
http.formLogin(); // form login 을 사용
http.httpBasic(); // http basic authentication 사용
}
}
- UserDetailsServiceAutoConfiguration 에서 InMemory 방식으로 유저를 자동 생성
-
따라서 설정 파일을 세팅하여 특정유저를 만들 수 있습니다.(사용가능성은 거의 없을 거 같지만..)
// application.properties spring.security.user.name=admin spring.security.user.password=123 spring.security.user.roles=ADMIN
인메모리 유저 설정
-
실제적인 프로젝트에서 사용하지는 않을 거 같지만, 메모리내에 유저를 저장하는 방식이 있습니다. 기본 설정대로 두면 인메모리 방식으로 유저를 자동 생성하지만 따로 저장할 수 없스니다.
// SecurityConfig file @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() // 인메모리 authentication 설정 .withUser("sc").password("{noop}123").roles("USER").and() .withUser("admin").password("{noop}!@#").roles("ADMIN"); }
-
InMemoryUserDetailsManager 를 bean 으로 등록하여, 외부에서 입력받은 유저를 메모리에 저장할 수도 있습니다.
// SecurityConfig file @Bean public InMemoryUserDetailsManager inMemoryUserDetailsManager() { return new InMemoryUserDetailsManager(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // UserDetailsService 를 InMemoryUserDetailsManager 로 설정 auth.userDetailsService(inMemoryUserDetailsManager()); }
// Controller @RestController @RequiredArgsConstructor public class AccountController { private final InMemoryUserDetailsManager inMemoryUserDetailsManager; @GetMapping("/account/inmemory/{role}/{username}/{password}") public Account joinInMemory(@ModelAttribute Account account) { inMemoryUserDetailsManager.createUser(new UserAccount(account)); return account; } } // UserAccount import org.springframework.security.core.userdetails.User; @Getter public class UserAccount extends User { private Account account; public UserAccount(Account account) { super(account.getUsername(), account.getPassword(), List.of(new SimpleGrantedAuthority("ROLE_" + account.getRole()))); this.account = account; } }
-
Test 이외의 용도로는 딱히 사용할 일이 없습니다.
JPA 연동
-
의존성 추가
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-data</artifactId> </dependency>
-
UserDetailsService : 스프링 시큐리티에서 DAO 인터페이스를 통해 데이터베이스에 있는 유저 정보를 가지고 인증을 하는 서비스 인터페이스
- loadUserByUsername 메서드 : user 정보를 가져와서 UserDetails type 의 구현체를 return 하도록 구현
- UserDetailsService 타입의 빈이 등록만 되어 있으면, security config 에서 AuthenticationManagerBuilder 에 UserDetailsService 를 설정하지 않아도 됨
// Entity
@Entity
public class Account {
@Id @GeneratedValue
private Long id;
@Column(unique = true)
private String username;
private String password;
private String role;
public void encodePassword(PasswordEncoder passwordEncoder) {
this.password = passwordEncoder.encode(this.password);
}
}
//UserDetailsService 구현체
@Service
@RequiredArgsConstructor
public class AccountService implements UserDetailsService {
private final AccountRepository accountRepository;
private final PasswordEncoder passwordEncoder;
//loadUserByUsername 에서 UserDetails type 의 구현체를 반환
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
final Account account = accountRepository.findByUsername(username);
return Optional.ofNullable(account)
.map(UserAccount::new)
.orElseThrow(() -> new UsernameNotFoundException(username));
}
// user 를 영속계층에 저장
@Transactional
public Account createNew(Account account) {
account.encodePassword(passwordEncoder);
return accountRepository.save(account);
}
}
PasswordEncoder
-
패스워드 인코딩 방식을 결정해주는 빈
-
BCryptPasswordEncoder 가 기본전략
// 기본전략으로 설정 @Bean public PasswordEncoder passwordEncoder() { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); }
'Spring > Spring Security' 카테고리의 다른 글
Spring Security (6) - LogoutFilter (0) | 2020.12.09 |
---|---|
Spring Security (5) - SecurityContextPersistenceFilter (0) | 2020.12.08 |
Spring Security (3) - Authentication (0) | 2020.09.09 |
SpringSecurity - Test 작성 (0) | 2020.09.07 |
Spring Security(2) - SecurityContext (0) | 2020.09.01 |