【问题标题】:"Debug symbol information is required (...)" after injecting modified Spring security expression language implementation注入修改后的Spring安全表达式语言实现后“需要调试符号信息(...)”
【发布时间】:2012-11-15 06:24:33
【问题描述】:

我有一个示例类来测试@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;
    }
}

您可以在@PreAuthorize 注释中注意到hasCustomRole(String expression),这是我添加的:

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。

编辑:

为了让这个问题更有趣,这就是我后来发现的:如果你用javap 查看.class 文件,“缺失”的调试信息实际上就在那里。所以类被正确编译了,但是 Spring 还是会抱怨......

【问题讨论】:

    标签: spring grails spring-security


    【解决方案1】:

    我解决了这个问题,但是,我不确定为什么我收到的日志中的异常和消息与问题相差甚远。

    我犯了一个错误,假设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)
      }
    }
    

    一切正常,测试通过。

    【讨论】:

      猜你喜欢
      • 2011-02-23
      • 2015-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-31
      • 2014-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多