没有注册bean解析器

时间:2015-07-17 09:58:22

标签: spring spring-security spring-boot

今天从Spring boot 1.2.5升级到1.3.0 BUILD-SNAPSHOT来电 @PreAuthorize失败:

示例:

@PreAuthorize("@defaultSecurityService.canDoSomething(authentication.principal.id, #objId)")
Result doSomething(@P("objId")String objId);

其中defaultSecurityService定义为:

@Service
public class DefaultSecurityService implements SecurityService {
    ...
    public boolean canDoSomething(String userId, String objId){
        return true; // 
    }
}

堆栈跟踪

Caused by: java.lang.IllegalArgumentException: Failed to evaluate expression '#oauth2.throwOnError(defaultSecurityService.canDoSomething(authentication.principal.id, #objId))'
at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:14)
...
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1057E:(pos 8): No bean resolver registered in the context to resolve access to bean 'defaultSecurityService'

我尝试过的事情:

make SecurityService extend [PermissionEvaluator ][1] and register a bean at Application.java`

 @Bean
 @Lazy
 public PermissionEvaluator permissionEvaluator(){
     return securityService;
 }`

但我仍然得到同样的错误

阅读spring security 4.0.2文档并未透露任何有关重大变更的相关资料

3 个答案:

答案 0 :(得分:5)

在新添加的bug中,这似乎是OAuth2AutoConfiguration。具体而言,它会引入OAuth2MethodSecurityConfiguration,其中DefaultMethodSecurityExpressionHandler会覆盖OAuth2MethodSecurityExpressionHandler而没有设置BeanResolver

如果您不使用OAuth2,那么最简单的解决方案是从类路径中删除Spring Security OAuth。

或者,如果您使用OAuth2AutoConfiguration,则可以使用以下内容排除@SpringBootApplication

@SpringBootApplication(exclude=OAuth2AutoConfiguration.class)

或者,如果您直接使用@AutoConfiguration,则可以使用以下内容:

@AutoConfiguration(exclude=OAuth2AutoConfiguration.class)

<强>更新

您也可以使用以下内容:

public class DelegatingMethodSecurityExpressionHandler implements
        MethodSecurityExpressionHandler {

    private final MethodSecurityExpressionHandler delegate;

    public DelegatingMethodSecurityExpressionHandler(
            MethodSecurityExpressionHandler delegate) {
        super();
        this.delegate = delegate;
    }

    public Object filter(Object filterTarget, Expression filterExpression,
            EvaluationContext ctx) {
        return delegate.filter(filterTarget, filterExpression, ctx);
    }

    public ExpressionParser getExpressionParser() {
        return delegate.getExpressionParser();
    }

    public EvaluationContext createEvaluationContext(
            Authentication authentication, MethodInvocation invocation) {
        return delegate.createEvaluationContext(authentication, invocation);
    }

    public void setReturnObject(Object returnObject, EvaluationContext ctx) {
        delegate.setReturnObject(returnObject, ctx);
    }
}

然后在您的配置中使用:

@Autowired(required = false)
List<AuthenticationTrustResolver> trustResolvers = new ArrayList<>();

@Autowired(required = false)
List<PermissionEvaluator> permissionEvaluators = new ArrayList<>();

@Bean
public MethodSecurityExpressionHandler securityExpressionHandler(ApplicationContext context) {
    OAuth2MethodSecurityExpressionHandler delegate = new OAuth2MethodSecurityExpressionHandler();
    delegate.setApplicationContext(context);
    if(trustResolvers.size() == 1) {
        delegate.setTrustResolver(trustResolvers.get(0));
    }
    if(permissionEvaluators.size() == 1) {
        delegate.setPermissionEvaluator(permissionEvaluators.get(0));
    }
    return new DelegatingMethodSecurityExpressionHandler(delegate);
}

我们必须将它包装在DelegatingMethodSecurityExpressionHandler中,因为Spring Boot的自动配置将用破坏的配置替换DefaultMethodSecurityExpressionHandler的任何子类。

答案 1 :(得分:2)

我遇到了与你相同的问题,我的bean负责管理REST控制器的安全性没有找到:

org.springframework.expression.spel.SpelEvaluationException: EL1057E:(pos 8): No bean resolver registered in the context to resolve access to bean 'communitySecurityAuthorizer
Rob的回复指出了我正确的方向(我认为我做错了,而不是标准的Spring OAuth2中的错误)。

我没有使用springboot,因为我正在制作一个webapp,我找到了解决问题的答案: https://github.com/spring-projects/spring-security-oauth/issues/730#issuecomment-219480394

问题实际上是来自bean解析器的null,所以这里是解决方案(上面链接的重新标记):

显式添加带有OAuth2WebSecurityExpressionHandler的@Bean     设置应用程序上下文

@Bean
    public OAuth2WebSecurityExpressionHandler oAuth2WebSecurityExpressionHandler(ApplicationContext applicationContext) {
        OAuth2WebSecurityExpressionHandler expressionHandler = new OAuth2WebSecurityExpressionHandler();
        expressionHandler.setApplicationContext(applicationContext);
        return expressionHandler;
    }

在ResourceServerConfigurerAdapter中,配置资源和     通过上面的Bean。

@Autowired
    private OAuth2WebSecurityExpressionHandler expressionHandler;
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.expressionHandler(expressionHandler);
    }

希望这个和其他人一样!

答案 2 :(得分:0)

正如Almiriad所说,生成OAuth2MethodSecurityExpressionHandler实例作为bean。

取而代之的是:

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

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

        ....
}

这样做:

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

        @Override
        protected MethodSecurityExpressionHandler createExpressionHandler() {
             return getOAuth2MethodSecurityExpressionHandler();
        }

        @Bean
        public OAuth2MethodSecurityExpressionHandler getOAuth2MethodSecurityExpressionHandler() {
             return new OAuth2MethodSecurityExpressionHandler();
        }

        ....
}

希望这是其他人!

相关问题