根据自定义条件保护对Java方法的访问

时间:2011-03-03 10:29:14

标签: java security spring aop

简而言之:我想根据某些条件允许/禁止执行Java方法。什么是最好的解决方案/机制/技术?

长问题,通过一个(诚然愚蠢的)例子:

假设我在车辆控制器中有多种方法,例如void openWindow(Window w)void openRoof()void keepSpeed(double speedKmh)。如果下雨,则不应调用openRoof,我们希望建立一个机制来确保它。同样,如果速度低于60公里/小时,则禁止keepSpeed,如果下雨很多,或openWindow,如果速度超过100 km/h,则为@ForbidIf('default:rain') openWindow(); @ForbidIf('default:speedBelow(60)') keepSpeed(); @ForbidIf('default:speedAbove(100)', 'custom:rainsALot') openWindow();

由于访问雨/速度传感器需要几行代码,并且这些条件在任何地方使用,我不想在方法体中使用使用断言或条件,但我宁愿使它们易于使用由域开发人员。此外,我希望将安全问题与打开窗口等的实际逻辑分开。更复杂的自定义条件也应该易于配置。

例如,我想要这个:

{{1}}

如果有帮助,这个应用程序是一个Spring驱动的客户端 - 服务器应用程序。

5 个答案:

答案 0 :(得分:2)

你可以使用一个简单的Spring AOP方面,像这样(未经测试):

@Aspect
public class SecurityAspect{

    @Pointcut("execution(@ForbidIf * *(*))")
    public void annotatedMethodCalled(){}

    @Before("annotatedMethodCalled() && @target(annotation) && target(bean)")
    public void beforeRestrictedMethodCall(
        final ForbidIf annotation, final Object bean){
        final Expression expression =
            new SpelExpressionParser().parseExpression(annotation.value());
        if(!Boolean.TRUE.equals(expression.getValue(bean))){
            throw new IllegalArgumentException();
        }
    }

}

答案 1 :(得分:1)

类似的东西在Spring Security中实现为expression based access control,但我认为它不适合你的情况。

但是,通过创建可以针对特定上下文评估SpEL expressions的方面,从头开始实现类似功能应该很容易。

答案 2 :(得分:1)

OP,评论Andreas_D的回答:“如果禁止执行,我想要引发运行时异常。在这种情况下,如果条件为false,则意味着在当前情况下应该从未调用此方法。 “

出了什么问题:

public void openWindow() {
    if (itsRaining()) {
        throw new IllegalStateException("Window should not open if it's raining");
    }
}

?我的意思是,做一个注释实际上是相同的,只是更复杂(特别是如果你的方法的条件增加复杂性,例如,如果窗口不下雨,如果下雨,下雪,车速> 100 KPh,风速度> 6,温度低于冰点等)。

当然,我也可能只是忽略了这一点。只是想暗示,过度思考,工程化或复杂化问题不是唯一可行的途径。当然,不想说使用AOP或注释是过度思考/工程/并发症是一个问题。可能也是基于简化示例的这篇文章。

答案 3 :(得分:0)

这是一个有趣的想法,虽然我看到了一些真正的问题。您可以注释方法并参考某些环境设置。但是如果禁止执行,那应该做什么呢?

考虑这个例子:

 @ForbidIf('default:durationIs(0))') double getSpeed(double distance);

并像

一样使用它
 double speed = getSpeed(distance);   // the duration is set globally in this example

如果持续时间值设置为0会发生什么 - 在这种情况下应该为速度分配什么?或者您是否想提出运行时异常?

在您的情况下,我们已经有两种方法来实现条件执行:

 // check before calling
 if (isSaveToOpenWindow())
   openWindow();

 public void openWindow() {
    if (!isSaveToOpenWindow())
      return;

    // open window
 }

答案 4 :(得分:0)

你需要AOP吗?装饰器模式可以更简单,并且需要更少的魔力。用以下内容包装实现:

class ProtectedWindowOpener implements WindowOpener {

   WindowOpener delegate ...

    void openWindow(Window w) {
        if (!allowOpen(w)) {
          throw new PermissionDeniedException...
        }
        delegate.openWindow(w);
    }

    boolean allowOpen(Window w) {
      // security logic here

    }
}

这使得安全逻辑保持独立,并且还具有不在代码中嵌入代码的优势,这意味着eclipse可以开展业务。