Spring安全性和@PostFilter

时间:2010-07-28 11:58:01

标签: spring-security

我有这个对象:

@Service
public class myBr {

    @PostFilter("filterObject.cellule.getId()==2")
    public List<Bibliotheque> getB() {
        return super.getAll();
    }

    public List<Bibliotheque> getA() {
        return getB();
    }
}

当我通过myBr.getB()的测试拨打电话时,@PostFilter已应用,但当我拨打myBr.getA()时,后置过滤器无效。

有没有办法处理这个问题,以便应用过滤器?

3 个答案:

答案 0 :(得分:9)

问题是@PostFilter是通过AOP技术应用的,但是您直接从getB()调用实例的getA()实现,而Spring AOP不会重写类。

这是发生了什么:

      +————————+      +——————————+
 getA |  pass  | getA |          |
—————>|·······>|—————>|          |———+
      |        |      |          |   |
      |  Bean  |      | Instance |   | this.getB
      |        |      |          |   |
 getB | filter | getB |          |   |
—————>|·······>|—————>|          |<——+
      |        |      |          |
      +————————+      +——————————+

Spring AOP将代理对象作为委托给bean的实际bean,通过使用JDK代理对象(当你有一个合适的接口时)或者使用CGLIB来合成对象 de novo < / em>的。对于getA,它直接通过,对于getB,它会将调用插入到后置过滤代码中。这很好,但它确实意味着当实例 - 您在this内获得getA的对象 - 用于直接调用getB时,它会跳过过滤器并直接跳转进入底层代码。

有四种可能的修复方法。

  1. 使用AspectJ来执行AOP代码的应用程序,该代码进行代码重写(代价是部署更复杂)。
  2. 将bean的句柄提供给实例(必须明确地完成;您不能自动装配它)并通过它调用getB
  3. getB放在另一个bean中。
  4. 对两种方法进行过滤。
  5. 我自己使用了#2选项(在我的特定情况下它比替代品更容易)并且效果很好,但最好的选择几乎肯定是#3,所以你不需要做自我调用“接口”方法;这种事情通常表明应用程序功能的分区不正确。

答案 1 :(得分:1)

我认为你已经解决了你的问题,但是如果有人想知道他的bean调用有类似的东西(我有与EJB相同的问题): 方法注释由容器/应用程序上下文或其处理注入的任何内容读取。而且,在这种情况下,需要某种拦截器来触发预期的行为,它只适用于来自bean的“外部”的调用,即包裹在bean中的代理对象。 在这种情况下getA()的作用是本地调用,所以从技术上讲,你的线程直接跳转到方法getB(),但它根本不考虑任何注释。

答案 2 :(得分:0)

我认为我能想到的唯一可行解决方案是在getA方法中添加 @PostFilter 注释。 这是因为注释的工作原理是在类实例周围创建一个代理对象,用于添加和处理表达式的建议(在这种情况下,在调用方法之后)这是一个面向方面的技巧但是当你从同一个方法中调用一个方法时例如,创建的建议永远不会被调用,这就是为什么它不会那样工作。