[TIL 66-2일 차] Spring Security 기초
5. 인가 아키텍처 - 인가 프로세스
단순히 인증에만 성공했다고 모든 Resource에 접근할 수 있다면 권한 부여(인가, Authorization)이라는 보안 요소를 무시하는 것
Spring Security에서 인증된 사용자에게 어떤 과정을 거쳐 애플리케이션 Resource에 대한 접근 권한을 부여하는지 살펴보자.
5-01. Spring Security의 컴포넌트로 보는 권한 부여(인가, Authorization) 처리 흐름
- Spring Security의 인가 과정은 보통 Filter Chain에서 수행됨

5-02. 인가 처리에서 사용되는 컴포넌트 세부 흐름
1) FilterSecurityInterceptor와 AuthorizationFilter
두 Filter 모두 요청이 들어올 때 인증 정보를 기반으로 권한 검사를 수행
FilterSecurityInterceptor- 가장 전통적인 인가(Authorization) 처리 Filter
- URL 요청에 대한 접근 권한을 검사함
AuthorizationFilter- Spring Security 5.5+에서 추가된 새로운 Filter
AuthorizationManager와 함께 동작클라이언트 요청이 들어오면 ➡️ (허용) ➡️ 보호된 자원 접근 / ➡️ AuthorizationFilter ➡️ (인가 검사) ➡️ 인가 결정 \ ➡️ (거부) ➡️ Access Denied
인가 결정 위임 메커니즘
- 인가는 보통
AuthorizationManager또는AccessDecisionManager에 위임 - Filter는 단순 “인가 검사 필요” 신호를 보냄
- Manager는 실제 권한 판단 수행
인가 성공/실패 시 처리 방식
- 인가 성공 시 다음 Filter나 Controller로 전달
- 인가 실패 시
AccessDeniedException이 발생하며,AccessDeniedHandler가 이것을 처리
2) AuthorizationManager
- 함수적 인터페이스로 정의 ➡️ 람다 표현식으로 쉽게 작성 가능
check()메서드로 인증 정보와 요청 정보를 입력 받아 접근 허용 여부를 결정
3) AuthorizationManager 구현체
RequestMatcherDelegatingAuthorizationManager
RequestMatcher를 통해 매치되는 권한 부여 처리
AuthorityAuthorizationManager
- 특정 권한(Authority)이 있는지 검사
AuthenticatedAuthorizationManager
- 인증(Authentication) 자체 여부만 검사
5-03. URL 기반 인가 설정
1) requestMatchers().access() 메서드 활용
- URL 요청 경로별로 권한을 제어 가능
- Spring Security 6(=Spring Boot 3.x)에서
antMatchers,mvcMatchers,regexMatchers가 제거되고,requestMatchers(...)한 가지로 통일 - 내부적으로 어떤 Matcher를 사용하느냐에 따라 Ant/MVC/Regex 전략이 적용
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").access(AuthorityAuthorizationManager.hasRole("ADMIN"))
.anyRequest().authenticated()
);
// 아래처럼 builder 메서드로 표현 가능
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/user/**").hasRole("USER")
.anyRequest().authenticated()
);
2) 경로 매칭 전략 (Ant/MVC/Regex)
Ant 패턴
REST API나 단순 경로 매칭에 적합
- 가장 흔함
*: 경로 요소 1개**: 하위 모든 디렉터리 포함
.requestMatchers("/admin/*").hasRole("ADMIN")
.requestMatchers("/api/**").hasRole("USER")
MVC 패턴
.requestMatchers(mvc.pattern("/articles/{id}")).hasRole("USER") // 경로 변수 인식
.requestMatchers(mvc.pattern(HttpMethod.POST, "/articles")).hasRole("WRITER")
Regex 패턴
.requestMatchers(new RegexRequestMatcher("^/file/[a-f0-9\\\\-]{36}$", null)).hasAuthority("FILE_READ")
3) 규칙 평가 순서와 우선 순위
- 규칙
- “요청 매칭 조건 + 인가 조건” 형태로 구성되며, 아래 한 줄 전체를 말함
- 예시:
.requestMatchers("/admin/*").hasRole("ADMIN")

4) 주요 인가 조건 메서드
| 메서드 | 의미 | 전형적 사용 |
|---|---|---|
permitAll() |
로그인 여부와 무관하게 모두 허용 | 정적 리소스, 공개 API |
anonymous() |
로그인하지 않은 사용자만 허용 | 로그인/회원가입 페이지 |
authenticated() |
로그인 사용자만 허용 | 일반 보호 API |
denyAll() |
누구도 접근 불가 | 임시 차단, 테스트 |
.requestMatchers("/login", "/signup").anonymous()
.requestMatchers("/assets/**").permitAll()
.anyRequest().authenticated()
5-04. 메서드 보안
URL 기반 인가 외에도 메서드 단위 보안 적용 가능
1) @EnableMethodSecurity
@Configuration
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
}
위 설정을 통해 @PreAuthorize, @PostAuthorize 애너테이션 사용 가능
2) @PreAuthorize, @PostAuthorize 활용
// 메서드 실행 `전` 인가 검사
@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long id) {
// ADMIN 권한을 가진 사용자만 실행 가능
}
// 메서드 실행 `후` 반환값 인가 검사
@PostAuthorize("returnObject.owner == authentication.name")
public User getUser(Long id) {
// 반환된 User 객체의 소유자가 현재 사용자일 때만 접근 허용
}
3) 메서드 파라미터 기반 동적 인가
SpEL(Spring Expression Language)을 사용하여 메서드 파라미터를 조건으로 활용할 수 있다.
- 현재 인증된 사용자 정보는
authentication또는principal를 통해 접근
// 파라미터 id와 인증 객체의 principal.id가 동일한 경우만 접근 허용
@PreAuthorize("#id == authentication.principal.id")
public void updateUser(Long id) {
// 현재 로그인한 사용자와 id가 같을 때만 실행됩니다.
}
5-05. 인가 이벤트와 예외 처리
1) AuthorizationEvent 발행과 구독
인가 과정에서 이벤트가 발행되며, 이를 구독해 로깅이나 모니터링을 수행할 수 있다.
@Component
public class CustomAuthorizationEventListener {
@EventListener
public void handleAuthEvent(AuthorizationEvent event) {
// ...
}
}
2) 인가 실패 시 예외 처리 전략
- 인가 실패 시
AccessDeniedException이 발생 AccessDeniedHandler가 인가 실패 시 발생한AccessDeniedException을 처리- 기본적으로
403 Forbidden응답 반응
Leave a comment