Authentication(너 누구니?), Authorization(너 접근 권한이 있니?)으로 분리되어 있다.
Authentication에서의 핵심 인터페이스
public interface AuthenticationManager {
Authentication authenticate(Authentication authentication)
throws AuthenticationException;
}
AuthenticationManager의 구현체 중 가장 많이 쓰이는 클래스
ProviderManager로 AuthenticationManager를 구현했을 때 구조
@Configuration
// Spring Security에서 제공하는 WebSecurity Config 설정을 위한 인터페이스 WebSecurityConfigurerAdapter 상속
public class ApplicationSecurity extends WebSecurityConfigurerAdapter {
... // web stuff here
@Autowired
// 빠르게 AuthetnciationManager를 구축하기 위해서 AuthenticationManagerBuilder 사용
// UserDetailsService를 커스텀하게 해줌
public void initialize(AuthenticationManagerBuilder builder, DataSource dataSource) {
builder.jdbcAuthentication().dataSource(dataSource).withUser("dave")
.password("secret").roles("USER");
}
}
이제 Authentication이 완료되었으니 Authorization을 살펴보자.
Authorization의 핵심 인터페이스
AccessDecisionManager는 3개의 구현체가 있으며 AccessDecisionVoter의 체인이다.
(마치 ProviderManager, AuthenticationProvider와의 관계처럼)
boolean supports(ConfigAttribute attribute);
boolean supports(Class<?> clazz);
//authetnciation, 보호할 object, 데코레이터인 attributes 고름
int vote(Authentication authentication, S object,
Collection<ConfigAttribute> attributes);
ConfigAttribute는 보통 user role의 이름이다. (ROLEADMIN, ROLE_AUDIT, ROLE어쩌고)
보통 isFullyAuthenticated() && hasRole('user')
이렇게 Authentication, Authroization을 확인한다.
Spring Security는 FilterChainProxy라는 필터를 내장하고 있다.
FilterChainProxy에서 일치하는 체인에 요청을 전송한다. 위의 구조로 이루어져있기 때문에 사용자는 어떤 필터를 사용해야 할지 신경쓰지 않아도 FilterChainProxy가 필터링을 한다. 이 때 이 모든 필터들은 Spring Container에 알려지지 않은 채로 진행한다.
@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER - 10)
public class ApplicationConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
// 개발자는 FilterChainProxy에 대해서 몰라도 된다.
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/match1/**")
.authorizeRequests()
.antMatchers("/match1/user").hasRole("USER")
.antMatchers("/match1/spam").hasRole("SPAM")
.anyRequest().isAuthenticated();
}
}