
출처
authenticated(인증되있어야 함)임을 요구한다.HttpSecurity 인스턴스를 사용할 수 있다는 것이다. @Bean
public SecurityFilterChain web(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().authenticated()
)
// ..
return http.build();
}authenticated() : 인증된 모든 사용자만 접근할 수 있도록 설정할 때 사용됩니다.permitAll() : 모든 사용자(인증되지 않은 사용자 포함)가 접근할 수 있도록 허용합니다.denyAll() : 모든 요청을 거부합니다. → 특정 리소스에 대해 접근을 차단할 때 사용됩니다.hasRole(String role) : 사용자가 특정 역할(ROLE_)을 가지고 있는지 확인합니다.hasAuthority(String authority) : 사용자가 특정 권한을 가지고 있는지 확인합니다.anyOf() : 전달된 여러 AuthorizationManager 중 하나만 만족하면 접근을 허용합니다.allOf() : 전달된 모든 AuthorizationManager 조건을 만족해야 접근을 허용합니다.custom(Predicate) : 커스텀 로직을 기반으로 동작하는 인가 매니저를 정의할 수 있습니다.
AuthorizationFilter 는 SecurityContextHolder에서 Authentication을 추출하고 처리하는 Supplier를 매개변수로 갖고 생성된다.AuthorizationFilter는 AuthorizationManager에게 Supplier<Authentication> 과 HttpServletRequest 를 전달한다.AuthorizationManager 는 요청을 authorizeHttpRequests 에 있는 패턴과 일치시키고 아래의 규칙을 수행한다.AuthorizationDeniedEvent 를 발행한다. 그리고 AccessDeniedException 예외가 던져진다. ExceptionTranslationFilter 가 AccessDeniedException 을 처리하게 된다.AuthorizationGrantedEvent 가 발행된다. 그리고, AuthorizationFilter 는 FilterChain 의 Filter 를 계속 진행한다.AuthorizationFilter 이전에 추가시틴다면, 이 필터 역시 인가 처리가 수행되지 않는다.또한, Spring Security는 메서드 레벨에서 인가 처리를 할 수 있도록 해준다.
Method Security 를 활성화 하기 위해서, 설정 파일 (@Configuration 클래스)에 @EnableMethodSecurity 를 추가해주어야 한다.
이제 @PreAuthorize, @PostAuthorize, @PreFilter, @PostFilter을 Spring에서 관리하는 클래스나 메서드에 추가하여 입력 매개변수와 반환 값을 포함한 메서드 호출에 대해서 인가처리를 할 수 있습니다.
AccessDeniedException 예외가 던져집니다.@PreAuthorize
사용자가 ADMIN 역할을 갖고 있는 경우에만 해당 메서드가 호출됩니다.
@Component
public class BankService {
@PreAuthorize("hasRole('ADMIN')")
public Account readAccount(Long id) {
// ... is only invoked if the `Authentication` has the `ROLE_ADMIN` authority
}
}
@PostAuthorize
사용자가 ADMIN 역할을 갖고 있는 경우에만 해당 메서드가 결과값을 반환합니다.
@Component
public class BankService {
@PostAuthorize("hasRole('ADMIN')")
public Account readAccount(Long id) {
// ... is only invoked if the `Authentication` has the `ROLE_ADMIN` authority
}
}
@PreFilter
accounts 에서 사용자의 이름과 일치한 Account 만 해당 메서드의 매개변수로서 수행됩니다.
@Component
public class BankService {
@PreFilter("filterObject.owner == authentication.name")
public Collection<Account> updateAccounts(Account... accounts) {
// ... `accounts` will only contain the accounts owned by the logged-in user
return updated;
}
}
@PostFilter
accounts 는 사용자의 이름과 일치한 Account 만 포함되어 반환됩니다.
@Component
public class BankService {
@PostFilter("filterObject.owner == authentication.name")
public Collection<Account> readAccounts(String... ids) {
// ... the return value will be filtered to only contain the accounts owned by the logged-in user
return accounts;
}
}
@Service
public class MyCustomerService {
@PreAuthorize("hasAuthority('permission:read')")
@PostAuthorize("returnObject.owner == authentication.name")
public Customer readCustomer(String id) { ... }
}

readCustomer 의 proxy method를 호출합니다.proxy의 advisor 들 중에서, @PreAuthorize 포인트컷과 일치하는 AuthorizationManagerBeforeMethodInterceptor 를 호출합니다.PreAuthorizeAuthorizationManager 의 check 함수를 호출합니다.@PreAuthorize 의 SpEL 표현식을 파싱하기 위해 MethodSecurityExpressionHandler 를 사용합니다.Supplier<Authentication> 과 MethodInvocation 을 포함하며 애노테이션의 SpEL 표현식에 대응되는 EvaluationContext를 MethodSecurityExpressionRoot 로 부터 생성합니다.context를 사용합니다. 특히, Supplier 로 부터 Authentication를 가져온 후, 권한을 확인합니다.AuthorizationDeniedEvent 를 발행하고 AccessDeniedException 예외를 던집니다.ExceptionTranslationFilter 가 AccessDeniedException 을 처리하며, 403 상태 코드를 응답에 전달합니다.@PostAuthorize 포인트컷과 일치하는 AuthorizationManagerAfterMethodInterceptor 를 호출합니다.PostAuthorizeAuthorizationManager 를 사용한다는 차이점이 있습니다.AuthorizationDeniedEvent 를 발행하고 AccessDeniedException 예외를 던집니다.ExceptionTranslationFilter 가 AccessDeniedException 을 처리하며, 403 상태 코드를 응답에 전달합니다.Tip
만약 메서드가 HTTP 요청의 context 에 의해 호출되지 않았다면, AccessDeniedException 을 처리하기 위한 핸들러를 따로 작성해야 합니다.