今天从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文档并未透露任何有关重大变更的相关资料
答案 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();
}
....
}
希望这是其他人!