5

我有一个示例类来测试@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.,这表明编译类时没有关于变量名的调试信息。但是,如果我不注入自己的 bean,一切都会正常工作。

缺少调试信息的原因可能是什么,以及如何解决?

这是一个 Grails 插件,为 Grails 2.0.4 开发,使用版本 1.2.7.3 的 spring-security-core 插件、版本 1.1 的 spring-security-acl 插件和 Spring Security 3.0.7.RELEASE。

编辑:

为了使问题更有趣,这是我后来发现的:如果您查看.class带有javap. 所以类被正确编译,但Spring无论如何都会抱怨......

4

1 回答 1

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

一切正常,测试通过。

于 2012-12-01T21:49:11.467 回答