Grails:在Spring Security表达式中调用bean方法

几天前,在使用Grails应用程序时,我处于一种需要从Spring安全SPEL表达式调用bean方法的情况。 我在使用Spring Security ACL插件中的@PreAuthorize批注,并想要执行以下操作:

@PreAuthorize("myService.canAccessUserProfile(#profileId)")
public Profile getUserProfile(long profileId) {
  ...
}

@PreAuthorize将SPEL表达式作为参数,对它进行评估以查看是否允许当前登录的用户访问getUserProfile()方法。 在此SPEL表达式中,我想调用myService的canAccessUserProfile()方法来执行安全检查。 在下面的内容中,我将说明执行此步骤所需的步骤。

幸运的是,可以通过在SPEL表达式中使用@符号作为前缀来引用bean:

@PreAuthorize("@myService.canAccessUserProfile(#profileId)")

但是,仅凭此更改是无法立即使用的,我们必须对Spring Security配置进行一些小的调整。

用于解析安全性表达式的SPEL表达式解析器(请参阅: SpelExpressionParser )将Bean的查找委托给BeanResolver 。 为了使上述安全性表达式起作用,我们必须创建一个BeanResolver实现并将其添加到Spring Security配置中。

为Grails创建BeanResolver非常简单:

class GrailsBeanResolver implements BeanResolver {

  GrailsApplication grailsApplication

  @Override
  public Object resolve(EvaluationContext evaluationContext, String beanName) throws AccessException {
    return grailsApplication.mainContext.getBean(beanName)
  }
}

我们只需要实现resolve()方法来满足BeanResolver接口。 在我们的示例中,我们将此工作委托给Grails应用程序的bean工厂。 因此,我们可以访问安全表达式中的所有可用bean。

现在,我们必须将bean解析器添加到SPEL评估上下文中(请参阅: EvaluationContext )。 这可以通过重写Spring Securities DefaultMethodSecurityExpressionHandler的createEvaluationContext()来完成:

class GrailsExpressionHandler extends DefaultMethodSecurityExpressionHandler {

  BeanResolver beanResolver

  @Override
  public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation method) {
    StandardEvaluationContext context = (StandardEvaluationContext) super.createEvaluationContext(auth, method)
    context.setBeanResolver(beanResolver)
    return context;
  }
}

顾名思义,createEvaluationContext()负责为安全性表达式创建评估上下文。 我们唯一要做的就是在创建EvaluationContext之后添加beanResovler。

之后,我们必须使用Spring Bean DSL在grails-app / conf / spring / resources.groovy中配置我们的两个新bean:

beans = {
  expressionHandler(GrailsExpressionHandler) {
    beanResolver              = ref('beanResolver')
    parameterNameDiscoverer   = ref('parameterNameDiscoverer')
    permissionEvaluator       = ref('permissionEvaluator')
    roleHierarchy             = ref('roleHierarchy')
    trustResolver             = ref('authenticationTrustResolver')  
  }

  beanResolver(GrailsBeanResolver) {
    grailsApplication = ref('grailsApplication')
  }
}

通常,expressionHandler bean将是如上所述的DefaultMethodSecurityExpressionHandler的实例。 因为我们希望Spring Security使用GrailsExpressionHandler,所以我们必须重写expressionHandler bean。 我们添加的唯一新依赖项是beanResolver属性。 DefaultMethodSecurityExpressionHandler(GrailsExpressionHandler的基类)需要expressionHandler的其他四个依赖项。 这些依赖关系已经由Spring Security插件提供。

现在应该可以使用@前缀引用bean并在安全性表达式中调用它们的方法。


翻译自: https://www.javacodegeeks.com/2013/11/grails-calling-bean-methods-in-spring-security-expressions.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值