“이 사용자가 이 URL에 접근할 수 있는가?”를 판단한다.
*[Client 요청]
↓
Authorization: Bearer <Access Token>
↓
Security Filter Chain 진입
↓
JWT Authentication Filter (인증) ← 수동 배치
└ Access Token 검증 (서명 + 만료)
└ Claim 파싱 (sub, role, exp)
└ Authentication 객체 생성 (UsernamePasswordAuthenticationToken)
└ SecurityContextHolder에 저장
↓
AuthorizationFilter(인가) ← Spring 자동 배치
└ SecurityContext에서 Authentication 조회
└ 요청 URL / Method 기준 권한 판단
└ 권한 없으면 → 403 Forbidden
↓
[Controller 진입]
└ @AuthenticationPrincipal로 userId 사용 가능*
SecurityConfig 설정 = AuthorizationFilter의 판단 기준
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll() // 규칙 1
.requestMatchers("/api/admin/**").hasRole("ADMIN") // 규칙 2
.anyRequest().authenticated() // 규칙 3
)
AuthorizationFilter 내부 동작
*// 우리가 작성 안 해도 Spring이 이렇게 동작
public void doFilter(...) {
// 1. 인증 정보 가져오기
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
// 2. 요청 URL 확인
String url = request.getRequestURI();
// 3. 설정과 비교
if (url.startsWith("/api/auth/")) {
// permitAll → 통과
} else if (url.startsWith("/api/admin/")) {
if (auth.hasRole("ADMIN")) {
// 통과
} else {
// 403 Forbidden
}
} else {
if (auth != null) {
// 통과
} else {
// 401 Unauthorized
}
}
filterChain.doFilter(request, response);
}*
인가 옵션 설정 예시
*.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll() // 누구나
.requestMatchers("/user/**").hasRole("USER") // USER 권한
.requestMatchers("/admin/**").hasRole("ADMIN") // ADMIN 권한
.requestMatchers("/api/**").hasAnyRole("USER", "ADMIN") // 둘 중 하나
.requestMatchers(HttpMethod.GET, "/posts/**").permitAll() // GET만 허용
.requestMatchers(HttpMethod.POST, "/posts/**").authenticated() // POST는 인증
.anyRequest().authenticated() // 나머지는 인증 필요
)*
커스텀 인가가 필요한 경우
*@PreAuthorize("hasRole('ADMIN')")
public void deleteUser() { ... }
@PreAuthorize("#userId == authentication.principal")
public void updateProfile(Long userId) { ... } // 본인만 수정 가능*