# 사전 및 사후 필터링의 필요성
- 메서드 호출은 허용하면서도 메서드로 보내는 매개 변수가 몇 가지 규칙을 따르는지 확인하고 싶을 수 있다.
- 메서드를 호출한 후 호출자가 반환된 값의 승인된 부분만 받을 수 있게 하려는 시나리오도 있을 수 있다.
- 이러한 기능을 필터링이라고 하며 두 가지 범주로 분류한다.
- 사전 필터링 : 프레임워크가 메서드를 호출하기 전에 매개 변수의 값을 필터링한다.
- 사후 필터 : 프레임워크가 메서드를 호출한 후 반환된 값을 필터링한다.
- @PreFilter 어노테이션이 지정된 메서드를 가로채고 정의된 기준에 따라 매개 변수로 제공되는 컬렉션의 값을 필터링한다.
- 아래의 소스를 참고해보자.
@Service
public class ProductService {
@PreFilter("filterObject.owner == authentication.name")
public List<Product> sellProduct(List<Product> products) {
return products ;
}
}
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ProductConfig extends WebSecurityConfigurerAdapter {
@Bean
public UserDetailsService userDetailsService() {
var manager = new InMemoryUserDetailsManager() ;
var u1 = User.withUsername("nikolai")
.password("12345")
.authorities("READ")
.build() ;
var u2 = User.withUsername("julien")
.password("12345")
.authorities("READ")
.build() ;
manager.createUser(u1);
manager.createUser(u2);
return manager ;
}
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance() ;
}
}
@RestController
public class Controller {
@Autowired
ProductService productService ;
@GetMapping("/sell")
public List<Product> sellProd() {
List<Product> products = new ArrayList<>() ;
products.add(new Product("beer", "nikolai")) ;
products.add(new Product("candy", "nikolai")) ;
products.add(new Product("chocolate", "julien")) ;
return productService.sellProduct(products) ;
}
}
- 주의할 점은 주어진 컬렉션을 애스펙트가 변경한다는 사실이다.
- 애스펙트가 같은 인스턴스에서 기준에 맞지 않는 요소를 제거하는 것이다.
- 변경이 불가능한 컬렉션을 제공하면 필터링 애스펙트가 컬렉션의 내용을 변경할 수 없어 실행 시 예외가 발생한다.
# 메서드 권한 부여를 위한 사후 필터링 적용
- 아래의 소스코드와 같이 List가 존재하는 비즈니스 로직을 수행시킨 후, 필터링 작업이 필요할 때 @PostFilter를 사용하여 사후 필터링을 구현할 수 있다.
@Service
public class ProductService {
@PostFilter("filterObject.owner == authentication.name")
public List<Product> sellProduct(List<Product> products) {
products.add(new Product("beer", "nikolai")) ;
products.add(new Product("candy", "nikolai")) ;
products.add(new Product("chocolate", "julien")) ;
return products ;
}
}