“调试符号信息是必需的(...)”注入修改后的Spring安全表达式语言实现 [英] "Debug symbol information is required (...)" after injecting modified Spring security expression language implementation

查看:117
本文介绍了“调试符号信息是必需的(...)”注入修改后的Spring安全表达式语言实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个示例类来测试 @PreAuthorize 注释,它看起来或多或少像这样:

<$
$ b @PreAuthorize(hasCustomRole('ROLE_CUSTOM')or hasRole('ROLE_EXAMPLE'))
Double getAccountBalance(Integer accountNumber) {
返回1234;
}

@PreAuthorize(#accountNumber> 400)
int getValue(Integer accountNumber){
return 1234;


$ / code>

您可以注意到 hasCustomRole字符串表达式) @PreAuthorize 注释中,我将其添加进来:

  public class CustomSecurityExpressionRoot extends SecurityExpressionRoot {
$ b $ public CustomSecurityExpressionRoot(Authentication auth){
super(auth);
}

public boolean hasCustomRole(String expression){
return / * some magic * /;


$ / code $ / pre

另外,我将 DefaultMethodSecurityExpressionHandler

  public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {

public CustomMethodSecurityExpressionHandler(){
super();

$ b @Override
public EvaluationContext createEvaluationContext(Authentication auth,MethodInvocation mi){
StandardEvaluationContext ctx =(StandardEvaluationContext)super.createEvaluationContext(auth,mi);
ctx.setRootObject(new CustomSecurityExpressionRoot(auth));
返回ctx;




$ b $ p
$ b

最后,所有内容都被包装在 resources.groovy

  beans = {
/ * ...一些东西...... * /

xmlns安全:'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 

但是如果我注入自己的实现,则前面的语句会导致:

 访问被拒绝
org.sprin gbswork.security.access.AccessDeniedException:访问被拒绝

经过进一步调查,我发现这个:

  prepost.PrePostAnnotationSecurityMetadataSource寻找目标类'class my.package.plugin.security.test中方法'getValue'的Pre / Post注释。 BankService'
prepost.PrePostAnnotationSecurityMetadataSource @ org.springframework.security.access.prepost.PreAuthorize(value =#accountNumber> 400)在特定方法上找到:public int my.package.plugin.security.test.BankService.getValue(java.lang.Integer)
method.DelegatingMethodSecurityMetadataSource添加安全方法[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安全对象:ReflectiveMethodInvocation:public int my.package.plugin.security.test.BankService.getValue(java.lang.Integer) ;目标是类[my.package.plugin.security.test.BankService $$ EnhancerByCGLIB $$ c590f9ac];属性:[[授权:'#accountNumber> 400',filter:'null',filterTarget:'null']]
aopalliance.MethodSecurityInterceptor先前已通过身份验证:org.springframework.security.authentication.TestingAuthenticationToken@b35bafc3:Principal:test;证书:[PROTECTED];已验证:true;详细信息:null;授予的权限:ROLE_TELLER
method.MethodSecurityEvaluationContext无法解析方法的方法参数名称:public final int my.package.plugin.security.test.BankService $$ EnhancerByCGLIB $$ c590f9ac.getValue(java.lang.Integer)。如果您在表达式中使用参数名称,则需要调试符号信息。

有趣的部分是如果您使用参数名称,则需要调试符号信息在表达式中。,这表明类编译时没有关于变量名的调试信息。但是,如果我不注入自己的bean,一切正常。



缺少调试信息的原因以及如何解决?



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

编辑: 为了让问题更有趣,这是我后来发现的:如果你用 javap 查看 .class 文件,missing调试信息实际上就在那里$ C>。因此,类编译正确,但春天抱怨...无论如何...

解决方案

我修正了这个问题,但是,我不完全确定为什么我收到的日志中的异常和消息远离问题。



假设 grails-app / conf / spring / resources.groovy 可以以类似于使用Grails构建的应用程序的方式使用。尽管文档没有明确指出在 resources.groovy 中配置的bean在这种情况下不起作用,但它指出 resources.groovy (在其他一些文件中)将被默认从包装中排除。



它并不能解释运行测试时的奇怪行为,但它不是

将Spring Security配置从 resources.groovy 移动到插件后描述符,如下所示:

  class MyOwnGrailsPlugin {

/ * ...有些东西。 .. * /

def doWithSpring = {
/ * ...一些春天的东西... * /

xmlns security:'http:// www .springframework.org / schema / security'

security.'global-method-security'('pre-post-annotations':'enabled'){
security.'expression-handler '(ref:'expressionHandler')
}

expressio nHandler(my.package.plugin.security.expression.CustomMethodSecurityExpressionHandler)
}
}

一切正常,测试通过。


I have an example class to test @PreAuthorize annotations, which looks more or less like this one:

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

You can notice hasCustomRole(String expression) in the @PreAuthorize annotation, which I'm adding in:

public class CustomSecurityExpressionRoot extends SecurityExpressionRoot {

    public CustomSecurityExpressionRoot(Authentication auth) {
        super(auth);
    }

    public boolean hasCustomRole(String expression) {
       return /* some magic */;
    }
}

Also, I'm extending DefaultMethodSecurityExpressionHandler in the following way:

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

In the end, everything is wrapped in 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)
}

Now, if I remove the security part from resources.groovy, I naturally lose the ability to use the hasCustomRole() method, but the following works:

assert bankService.getValue(500) == 1234

But if I inject my own implementation, the previous statement causes:

Access is denied
org.springframework.security.access.AccessDeniedException: Access is denied

After further investigation I found this:

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.

The interesting part is Debug symbol information is required if you are using parameter names in expressions., which suggests that classes are compiled without debug information about variable names. But everything works fine if I don't inject my own bean.

What could be the reason for the missing debugging info, and how to fix it?

It's a Grails plugin, developed for Grails 2.0.4, using spring-security-core plugin at version 1.2.7.3, spring-security-acl plugin at version 1.1, and Spring Security 3.0.7.RELEASE.

EDIT:

To make the issue more interesting, this is what I discovered later: the "missing" debug information is actually there, if you look into .class files with javap. So classes are compiled correctly, but Spring complains anyway...

解决方案

I fixed the issue, however, I'm not exactly sure why the exceptions and messages in logs I had been getting were so far from the problem.

I did one mistake assuming that grails-app/conf/spring/resources.groovy can be used in similar way as in applications built with Grails. And although the documentation doesn't explicitly say that beans configured in resources.groovy won't work in this case, it states that resources.groovy (among some other files) will be by default excluded from packaging.

It doesn't explain the strange behavior while running tests, but it's not a good place for this kind of configuration.

After moving the Spring Security configuration from resources.groovy into the plugin descriptor, in the following way:

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

everything works fine and the test passes.

这篇关于“调试符号信息是必需的(...)”注入修改后的Spring安全表达式语言实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆