没有注册 bean 解析器 [英] Getting No bean resolver registered
问题描述
今天从Spring boot 1.2.5
升级到1.3.0 BUILD-SNAPSHOT
后调用@PreAuthorize
失败:
After upgrading today from Spring boot 1.2.5
to 1.3.0 BUILD-SNAPSHOT
Calling
@PreAuthorize
fails:
示例:
@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
扩展 [PermissionEvaluator][1] 并注册一个 bean在
Application.java`
make SecurityService
extend [PermissionEvaluator][1] and register a bean
at
Application.java`
@Bean
@Lazy
public PermissionEvaluator permissionEvaluator(){
return securityService;
}`
但我仍然遇到同样的错误
But i'm still getting the same error
阅读 spring security 4.0.2 文档没有发现任何有关重大更改的相关材料
Reading the spring security 4.0.2 documentation didn't reveal any relevant material about breaking changes
推荐答案
这似乎是一个 bug/springframework/boot/autoconfigure/security/oauth2/OAuth2AutoConfiguration.java" rel="noreferrer">OAuth2AutoConfiguration.具体来说,它引入了 OAuth2MethodSecurityConfiguration 使用没有 BeanResolver 的
OAuth2MethodSecurityExpressionHandler
覆盖 DefaultMethodSecurityExpressionHandler
设置.
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.
如果您没有使用 OAuth2,那么最简单的解决方案是从您的类路径中删除 Spring Security OAuth.
If you are not using OAuth2, then the easiest solution is to remove Spring Security OAuth from your classpath.
或者,如果您使用 @SpringBootApplication
,您可以使用以下内容排除 OAuth2AutoConfiguration
:
Alternatively, you can exclude the OAuth2AutoConfiguration
using the following if you use @SpringBootApplication
:
@SpringBootApplication(exclude=OAuth2AutoConfiguration.class)
或者,如果您直接利用 @AutoConfiguration
,您也可以使用以下内容:
alternatively you can use the following if you leverage @AutoConfiguration
directly:
@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);
}
}
然后在您的配置中使用:
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);
}
我们必须将它包装在 DelegatingMethodSecurityExpressionHandler 中,因为 Spring Boot 的自动配置将用损坏的配置替换 DefaultMethodSecurityExpressionHandler
的任何子类.
We have to wrap it in the DelegatingMethodSecurityExpressionHandler because Spring Boot's auto config will replace any subclass of DefaultMethodSecurityExpressionHandler
with the broken configuration.
这篇关于没有注册 bean 解析器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!