Reputation: 758
I would like to use @PostFilter
on method returning Optional
.
Spring DefaultMethodSecurityExpressionHandler
currently not handling Optional
but I could make a simple decorator and transform the Optional
into Stream
. How can I register such decorator without creating a new GlobalMethodSecurityConfiguration
as I am using an internal framework I can't modify.
Is there another way to do that ?
Upvotes: 2
Views: 434
Reputation: 51
The easier way to do it is like this:
import java.util.Collection;
import java.util.Optional;
import java.util.stream.Stream;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.stereotype.Service;
@Service
public class AnyTypeMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler implements MethodSecurityExpressionHandler {
@Override
public Object filter(final Object filterTarget, final Expression filterExpression, final EvaluationContext ctx) {
if (filterTarget instanceof Collection || filterTarget != null && filterTarget.getClass().isArray() || filterTarget instanceof Stream) {
return super.filter(filterTarget, filterExpression, ctx);
}
if (filterTarget instanceof Optional) {
return ((Stream<?>) super.filter(((Optional<?>) filterTarget).stream(), filterExpression, ctx)).findAny();
}
return ((Stream<?>) super.filter(Stream.ofNullable(filterTarget), filterExpression, ctx)).findAny().orElse(null);
}
}
That will handle Optional
s and also plain Java Objects (making them null
if they are filtered).
Upvotes: 5
Reputation: 758
The solution was as simple as declaring the decorator as a @Service
@Service
public class OptionalAdapterMethodSecurityExpressionHandler implements MethodSecurityExpressionHandler {
private final MethodSecurityExpressionHandler handler
public CustomMethodSecurityExpressionHandler(MethodSecurityExpressionHandler handler){
this.handler = handler;
}
@Autowired
public CustomMethodSecurityExpressionHandler(ApplicationContext applicationContext) {
this(new DefaultMethodSecurityExpressionHandler());
((DefaultMethodSecurityExpressionHandler)this.original).setApplicationContext(applicationContext);
}
@Override
public Object filter(Object filterTarget, Expression filterExpression, EvaluationContext ctx) {
if (filterTarget instanceof Optional) {
final List<?> optionalUnfilteredList = ((Optional<?>) filterTarget).stream()
.collect(Collectors.toList());
final List<?> optionalFilteredList = (List<?>) this.handler.filter(optionalUnfilteredList, filterExpression, ctx);
return optionalFilteredList.stream()
.findFirst();
}
return this.handler.filter(filterTarget, filterExpression, ctx);
}
...
}
Upvotes: 0