我有一个示例类来测试@PreAuthorize
注释,它看起来或多或少像这样:
class BankService {
@PreAuthorize("hasCustomRole('ROLE_CUSTOM') or hasRole('ROLE_EXAMPLE')")
Double getAccountBalance(Integer accountNumber) {
return 1234;
}
@PreAuthorize("#accountNumber > 400")
int getValue(Integer accountNumber) {
return 1234;
}
}
您可以注意到hasCustomRole(String expression)
注释中的@PreAuthorize
,我正在添加:
public class CustomSecurityExpressionRoot extends SecurityExpressionRoot {
public CustomSecurityExpressionRoot(Authentication auth) {
super(auth);
}
public boolean hasCustomRole(String expression) {
return /* some magic */;
}
}
另外,我正在通过以下方式扩展DefaultMethodSecurityExpressionHandler
:
public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
public CustomMethodSecurityExpressionHandler() {
super();
}
@Override
public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {
StandardEvaluationContext ctx = (StandardEvaluationContext) super.createEvaluationContext(auth, mi);
ctx.setRootObject(new CustomSecurityExpressionRoot(auth));
return ctx;
}
}
最后,所有内容都包含在resources.groovy
:
beans = {
/* ... some stuff ... */
xmlns security:'http://www.springframework.org/schema/security'
security.'global-method-security'('pre-post-annotations': 'enabled') {
security.'expression-handler'(ref: 'expressionHandler')
}
expressionHandler(my.package.plugin.security.expression.CustomMethodSecurityExpressionHandler)
}
现在,如果我从resources.groovy
删除安全部分,我自然会失去使用hasCustomRole()
方法的能力,但以下工作原理:
assert bankService.getValue(500) == 1234
但是如果我注入我自己的实现,前面的语句会导致:
Access is denied
org.springframework.security.access.AccessDeniedException: Access is denied
经过进一步调查后,我发现了这一点:
prepost.PrePostAnnotationSecurityMetadataSource Looking for Pre/Post annotations for method 'getValue' on target class 'class my.package.plugin.security.test.BankService'
prepost.PrePostAnnotationSecurityMetadataSource @org.springframework.security.access.prepost.PreAuthorize(value=#accountNumber > 400) found on specific method: public int my.package.plugin.security.test.BankService.getValue(java.lang.Integer)
method.DelegatingMethodSecurityMetadataSource Adding security method [CacheKey[my.package.plugin.security.test.BankService; public int my.package.plugin.security.test.BankService.getValue(java.lang.Integer)]] with attributes [[authorize: '#accountNumber > 400', filter: 'null', filterTarget: 'null']]
aopalliance.MethodSecurityInterceptor Secure object: ReflectiveMethodInvocation: public int my.package.plugin.security.test.BankService.getValue(java.lang.Integer); target is of class [my.package.plugin.security.test.BankService$$EnhancerByCGLIB$$c590f9ac]; Attributes: [[authorize: '#accountNumber > 400', filter: 'null', filterTarget: 'null']]
aopalliance.MethodSecurityInterceptor Previously Authenticated: org.springframework.security.authentication.TestingAuthenticationToken@b35bafc3: Principal: test; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_TELLER
method.MethodSecurityEvaluationContext Unable to resolve method parameter names for method: public final int my.package.plugin.security.test.BankService$$EnhancerByCGLIB$$c590f9ac.getValue(java.lang.Integer). Debug symbol information is required if you are using parameter names in expressions.
有趣的部分是Debug symbol information is required if you are using parameter names in expressions.
,这表明编译的类没有关于变量名的调试信息。但如果我不注射自己的豆,一切都会正常。
缺少调试信息的原因是什么,以及如何修复它?
这是一个为Grails 2.0.4开发的Grails插件,使用版本为1.2.7.3的spring-security-core插件,版本为1.1的spring-security-acl插件和Spring Security 3.0.7.RELEASE。
修改
为了使问题更有趣,这是我后来发现的:如果您使用.class
查看javap
文件,那么“缺少”的调试信息实际上就存在了。所以类是正确编译的,但是Spring总是抱怨......
答案 0 :(得分:0)
我修复了这个问题,但是,我不确定为什么我所获得的日志中的异常和消息远离问题。
假设grails-app/conf/spring/resources.groovy
的使用方式与使用Grails构建的应用程序类似,我犯了一个错误。虽然文档没有明确说明在resources.groovy
中配置的bean在这种情况下不起作用,但它声明resources.groovy
(在某些其他文件中)默认情况下将从打包中排除。
它没有解释运行测试时的奇怪行为,但它不是这种配置的好地方。
将Spring Security配置从resources.groovy
移动到插件描述符后,按以下方式:
class MyOwnGrailsPlugin {
/* ... some stuff ... */
def doWithSpring = {
/* ... some spring stuff ... */
xmlns security:'http://www.springframework.org/schema/security'
security.'global-method-security'('pre-post-annotations': 'enabled') {
security.'expression-handler'(ref: 'expressionHandler')
}
expressionHandler(my.package.plugin.security.expression.CustomMethodSecurityExpressionHandler)
}
}
一切正常,测试通过。