Getting No bean resolver registered

穿精又带淫゛_ 提交于 2021-02-07 13:28:32

问题


After upgrading today from Spring boot 1.2.5 to 1.3.0 BUILD-SNAPSHOT Calling @PreAuthorize fails:

example:

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

where defaultSecurityService is defined as:

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

Stack trace

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'

what i've tried:

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

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

But i'm still getting the same error

Reading the spring security 4.0.2 documentation didn't reveal any relevant material about breaking changes


回答1:


This appears to be a bug in the newly added OAuth2AutoConfiguration. Specifically it brings in OAuth2MethodSecurityConfiguration which overrides the DefaultMethodSecurityExpressionHandler with a OAuth2MethodSecurityExpressionHandler that does not have a BeanResolver set.

If you are not using OAuth2, then the easiest solution is to remove Spring Security OAuth from your classpath.

Alternatively, you can exclude the OAuth2AutoConfiguration using the following if you use @SpringBootApplication:

@SpringBootApplication(exclude=OAuth2AutoConfiguration.class)

alternatively you can use the following if you leverage @AutoConfiguration directly:

@AutoConfiguration(exclude=OAuth2AutoConfiguration.class)

UPDATE

You can also use something like this:

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);
    }
}

Then in your configuration use:

@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);
}

We have to wrap it in the DelegatingMethodSecurityExpressionHandler because Spring Boot's auto config will replace any subclass of DefaultMethodSecurityExpressionHandler with the broken configuration.




回答2:


I had the same problem than you, my bean in charge of managing security on a REST controller wasn't found:

org.springframework.expression.spel.SpelEvaluationException: EL1057E:(pos 8): No bean resolver registered in the context to resolve access to bean 'communitySecurityAuthorizer

Rob's reply pointed me in the right direction (I thought I was doing it wrong, not that it was a bug in the standard Spring OAuth2).

I don't use springboot as I'm making a webapp and I found the answer that solved my problem here: https://github.com/spring-projects/spring-security-oauth/issues/730#issuecomment-219480394

The problem comes in fact from the bean resolver which is null so here is the solution (retranscription of the link above):

Add a @Bean with OAuth2WebSecurityExpressionHandler that explicitly sets the application context

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

In the ResourceServerConfigurerAdapter, configure the resources and pass in the Bean above.

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

Hope this'll others !




回答3:


As Almiriad has said, generate the OAuth2MethodSecurityExpressionHandler instance as a bean.

Instead do that:

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

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

        ....
}

do this:

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

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

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

        ....
}

Hope this'll others !



来源:https://stackoverflow.com/questions/31473171/getting-no-bean-resolver-registered

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!