首页 > 解决方案 > JPA - 带有@PostFilter 的 findById:过滤器目标必须是集合或数组类型,但是是可选的

问题描述

我刚刚将我的应用程序更新到 Spring Boot 2.0.3.RELEASE 并发现我在 @PostFilter 中的 SpEL 不再工作了:

@PreAuthorize("isFullyAuthenticated()")
@PostFilter("hasAuthority('ADMIN') or @companyService.isOwnerOfPerson(#id, principal)")
@Override
public Optional<Person> findById(@Param("id") String id);

错误是 org.springframework.security.authentication.InternalAuthenticationServiceException: Filter target must be a collection or array type, but was Optional[Person ...]

我已经看到在https://jira.spring.io/browse/SPR-15878上对此进行了讨论,但我试图解决并运行:我扩展了 DefaultMethodSecurityExpressionHandler 并按照票证中的建议覆盖了 setReturnObject 方法上面引用的:

public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {

    @Override
    public void setReturnObject(Object returnObject, EvaluationContext ctx) {
        if (returnObject instanceof Optional) {
            Optional<?> optional = (Optional<?>)returnObject;

            Object value = null;
            if (optional.isPresent()) {
                value = optional.get();
            }

            ((MethodSecurityExpressionOperations) ctx.getRootObject().getValue())
            .setReturnObject(value);
        } else {
            super.setReturnObject(returnObject, ctx);
        }
    }

}

接下来,我将方法安全性配置如下:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return new CustomMethodSecurityExpressionHandler();
    }

}

我不确定这是否应该是这样,但我知道它还不起作用;)

任何人都可以帮忙吗?

标签: securityspring-data-jpaspring-el

解决方案


出现此错误是因为 @PostFilter 仅适用于集合(或数组)作为返回值,而 findById 仅返回单个值的可选值。您可以在异常消息中看到它:

过滤器目标必须是集合或数组类型


推荐阅读