스프링 시큐리티는 스프링 프레임워크 밖에서 최대한 인증과 권한을 처리할려고 하기에
굉장히 복잡한 과정을 거친다.
스프링 프레임워크에서 최대한 벗어나려고 하는 이유는 뭘까.. 이건 별도로 알아봐야겠음.
Spring Security의 동작은 필터 체인을 Dispatcher Servlet 앞에 두어
요청을 가로채는 것부터 시작한다.
그 후 과정은 역순으로 가서 최종적으로 Security Context에 인증 정보가 남고
이후에는 권한 처리를 통해 서블릿으로 넘어갈 수 있다
접근 권한 자체가 없는 경우 별도의 오류처리를 해야 한다.
기본적으로 UserPasswordAuthenticationFilter(Token)이 loginForm을 내려주지만 Rest API의 경우 별도의 폼이 존재하지 않아 이를 JSON으로 내려줄 수 있어야 한다.
따라서 UserPasswordAuthenticationFilter에 JSON 오류 처리 메소드가 존재해야 한다.
// Http
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic.disable()
.csrf().disable()
.headers().frameOptions().disable()
.and()
.authorizeRequests()
// 권한 설정
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/info").hasRole("USER")
.antMatchers("/**").authenticated()
.and()
.formLogin().disable()
.and()
// 403 예외처리 핸들링
.exceptionHandling().accessDeniedPage("/user/denied");
}
// DetailService를 통해 User 접근, 인코딩해서 저장
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
스프링 시큐리티의 모든 인증 로직은 AuthenticationManager를 통해 이루어진다
따라서 AuthenticationMangerBuilder를 이용하여 생성
AuthenticationManger는 UserDetailService 인터페이스를 구현
이후 loadByUserName() 메소드를 UserService에서 구현하여 사용
필터 체인에서 Authentication Provider를 무엇으로 하냐에 따라 인증 구현이 다르다
Session Provider라면 세션 인증, Token Provider라면 토큰 인증이 된다
Token Provider를 사용했을 때 인증 로직의 동작 구조다
기존 필터 체인의 동작에 토큰을 발급받는 과정만이 추가되는데 조금 더 자세히 보면 다음과 같다.
토큰 유효성 검사
토큰 발급