<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
Using genereated security password: (36자리 비밀번호)
스프링 시큐리티 기본 구성 클래스하기
WebSecurityConfigureAdapter를 지원하지 않음 -> configure를 오버라이딩하여 사용 불가
(이유) 컴포넌트 기반 시큐리티(component-based security)를 위함
5.7 이후부터는 SecurityChain을 Bean 등록하여 시큐리티 구성
5.7 이전
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/design", "/orders")
.access("hasRole('ROLE_USER')")
.antMatchers("/", "/**").access("permitAll")
.and()
.httpBasic();
}
}
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/design", "/orders")
.access("hasRole('ROLE_USER')")
.antMatchers("/", "/**").access("permitAll")
.and()
.httpBasic();
return http.build();
}
}
한 명 이상의 사용자 처리를 위한 사용자 스토어 구성 방법
1) 인메모리 사용자 스토어
2) JDBC 기반 사용자 스토어
3) LDAP 기반 사용자 스토어
4) 커스텀 사용자 명세 서비스
인메모리 사용자 스토어
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user1")
.password("{noop}password1")
.authorities("ROLE_USER");
}
@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user1")
.password("{noop}password1")
.authorities("ROLE_USER")
.and()
.withUser("user2")
.password("{noop}password2")
.authorities("ROLE_USER");
}
JDBC 기반 사용자 스토어
public static final String DEF_USERS_BY_USERNAME_QUERY =
"select username, password, enabled " +
"from users " +
"where username = ?";
public static final String DEF_AUTHORITIES_BY_USERNAME_QUERY =
"select username, authority " +
"from authorities " +
"where username = ?";
public static final DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY =
"select g.id, g.group_name, ga.authority " +
"from authorities g, group_members gm, group_authorites ga " +
"where gm.username = ? " +
"and g.id = ga.group_id " +
"and g.id = gm.group_id";
...usersByUsernameQuery("select ... from ... where username=?");
※ 패스워드의 암호화LDAP 기반 사용자 스토어
네트워크 상에서 조직이나 개인, 파일, 디바이스 등을 찾아볼 수 있게 해주는 프로토콜
TCP/IP 위에서 운용되는 프로토콜
※ DAP: OSI계층 전체의 프로토콜을 지원 → 네트워크의 자원 소비가 많음
LDAP 모델
1) information 모델: 데이터의 형태와 데이터를 디렉토리 구조로 정보를 저장하는 방식
2) Naming 모델: 디렉토리 구조에서 각 Entry의 식별 및 구성에 대한 설명
3) Functional 모델: 디렉토리에서 작업하는 명령
4) Security 모델: 접근하는 사용자 인증과 데이터 접근 권한을 통한 서비스 보호
사용자 인증 커스터마이징
public interface UserDetailsService {
UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/design", "/orders")
.access("hasRole('ROLE_USER')")
.antMatchers("/", "/**").access("permitAll");
return http.build();
}
authorizeRequests: URL 경로와 패턴 및 해당 경로의 보안 요구사항 구성
antMatchers: 지정된 경로와 패턴 일치를 검사 → 우선적으로 처리되어야 함
(순서를 바꿀 시 모든 요청의 사용자에게 permit 적용)
요청 경로가 보안처리 되는 방법을 정의하는 메소드
스프링 시큐리티에서 확장된 SpEL(스프링 표현식 언어)
public String processOrder(@Valid Order order, Errors errors,
SessionStatus sessionStatus, Principal principal) {
...
User user = userRepository.findByUsername(principal.getName());
order.setUser(user);
...
}
public String processOrder(@Valid Order order, Errors errors,
SessionStatus sessionStatus, Authentication authentication) {
...
User user = (User) authentication.getPrincipal();
order.setUser(user);
...
}
Authentication authentication =
SecurityContextHolder.getContext().getAuthentication();
User user = (User) authentication.getPrincipal();
public String processOrder(@Valid Order order, Errors errors,
SessionStatus sessionStatus,
@AuthenticationPrincipal User user) {
...
order.setUser(user);
...
}