이 글은 정수원님의 Infrean 강의를 학습한 내용을 정리하여 작성합니다.
Authorization
- 당신에게 무엇이 허가 되었는지 증명하는 것
- 사용자가 Web Application의 특정 자원에 접근하려 할 때 해당 사용자가 Authenticated 즉 인증을 받았는지 여부를 판단한다.
- 인증을 받은 사용자가 다시 특정 자원에 접근하고자 할 때 해당 사용자의 권한이 Resource에 접근할 만한 자격이 있는지 심사해서 최종적으로 판단하는 것을 인가라고 한다.
- 인증 -> 인가
스프링 시큐리티가 지원하는 권한 계층
- 웹 계층
- URL 요청에 따른 메뉴 혹은 화면단위의 레벨 보안
- 서비스 계층
- 화면 단위가 아닌 메소드 같은 기능 단위의 레벨 보안
- 도메인 계층 (Access Control List, 접근제어목록)
- 객체 단위의 레벨 보안
- 해당 강의에서는 웹 계층과 서비스 계층만 다루고 도메인 계층은 다루지 않는다.
FilterSecurityInterceptor
- 마지막에 위치한 필터로써 인증된 사용자에 대하여 특정 요청의 승인/거부 여부를 최종적으로 결정한다.
- 인증객체 없이 보호자원에 접근을 시도할 경우 AuthenticationException을 발생시킨다.
- 인증 후 자원에 접근 가능한 권한이 존재하지 않을 경우 AccessDeniedException을 발생시킨다.
- 권한 제어 방식 중 HTTP 자원의 보안을 처리하는 필터
- 권한 처리를 AccessDecisionManager에게 맡긴다.
흐름도
- 사용자가 특정 자원에 접근을 시도한다.
- FilterSecurityInterceptor가 요청을 받아 인증 여부를 체크한다.
- 사용자가 인증(Authentication) 객체를 가지고 있는지 판단한다.
- 존재하지 않으면 AuthenticationException을 발생시키고 더이상 인가 처리를 하지 않는다.
- 인증 예외는 ExceptionTranslationFilter가 받아 로그인 페이지로 이동시킨다.
- 인증 객체가 존재하는 경우 SecurityMetadataSource 클래스가 사용자가 요청한 자원에 접근하기 위해 필요한 권한 정보를 조회해서 전달한다.
- 만약 특정 자원에 설정된 권한이 없는 경우(Null일 경우) 권한 심사를 하지 않는다.
- 해당 자원에 권한정보가 존재하는 경우 권한정보를 AccessDesicionManager 클래스에게 전달한다.
- AccessDecisionManager는 최종 심의 결정자이다.
- 내부적으로 AccessDesisionVoter(심의자) 클래스를 통해 심의요청을 수행한다.
- AccessDecisionVoter는 사용자가 해당 자원에 접근할 자격이 있는지 판단한다.
- 승인 또는 거부를 AccessDecisionManager에게 전달한다.
- 내부적으로 AccessDesisionVoter(심의자) 클래스를 통해 심의요청을 수행한다.
- AccessDecisionManager는 전달받은 값 (승인 또는 거부)을 통해 사용자가 해당 자원에 접근 가능한지 판단한다.
- 만약 접근이 승인되지 않으면 AccessDeniedException 예외가 발생한다.
- 인가 예외 역시 ExceptionTranslationFilter가 받아 예외 처리를 수행한다.
- 접근이 승인되면 사용자에게 해당 자원에 대한 접근이 허용된다.
- 만약 접근이 승인되지 않으면 AccessDeniedException 예외가 발생한다.
실습
SecurityConfig
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authz) -> authz
.antMatchers("/user").hasRole("USER")
.anyRequest().permitAll()
)
.formLogin();
return http.build();
}
}
- "/user" 자원에 "USER" 권한을 가진 사용자만 접근 가능하도록 설정한다.
- 나머지는 모두 접근이 가능하도록 설정한다.
SecurityController
@RestController
public class SecurityController {
@GetMapping("/")
public String index() {
return "home";
}
@GetMapping("/user")
public String user() {
return "user";
}
}
실행
사용자에게 권한이 없는 경우
- 사용자가 "/user" 요청을 수행하면 다음과 같이 로그인 페이지로 이동한다.
- 사용자가 로그인을 수행하더라도 해당 사용자는 현재 USER 권한을 가지고 있지 않아 접근이 거부된다.
사용자에게 USER 권한이 부여된 경우
- 다음과 같이 사용자에게 USER 권한을 부여한다.
- 서버 재실행 후 USER 권한을 가진 사용자가 "/user" 자원에 접근한 결과는 다음과 같다.
'스프링 시큐리티 > 스프링 시큐리티 주요 아키텍처 이해' 카테고리의 다른 글
스프링 시큐리티 필터 및 아키텍처 정리 (0) | 2023.02.10 |
---|---|
인가 결정 심의자 - AccessDecisionManager, AccessDecisionVoter (0) | 2023.02.10 |
인증 처리자 - AuthenticationProvider (0) | 2023.02.08 |
인증 관리자: AuthenticationManager (0) | 2023.02.08 |
인증 흐름 이해 - AuthenticationFlow (0) | 2023.01.31 |