출처
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 을 처리하기 위한 핸들러를 따로 작성해야 합니다.