Grails 自定义安全评估器 [英] Grails custom security evaluator

查看:14
本文介绍了Grails 自定义安全评估器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个应用程序,它必须执行对象级安全检查,检查将由服务进行,因为它需要对单独的应用程序进行 REST 调用.因此,我无法使用 Spring Security 角色或 ACL,因为这些信息都不会本地存储在应用程序中.我正在尝试找到一种优雅的方法来处理这个问题,这里有两个我能想到的选择:

I'm working on an app that has to do object level security checks, and the checks will be made by a service because it will need to make REST calls to a separate application. Because of this I'm not able to use Spring Security roles or ACLs because none of this information will be stored locally in the app. I'm trying to find an elegant way to handle this, and here are two options I can think of:

1) 创建一个自定义注解来检查权限

1) Create a custom annotation that will check permissions

2) 扩展 Spring 安全注释权限检查(可能使用 Permission Evaluator?),让我编写检查访问的逻辑

2) Extend a Spring security annotation permission check (possibly with Permission Evaluator?) that lets me write the logic for checking access

对于#1,我创建了一个自定义注释,并使用过滤器来读取注释并检查访问权限,尽管这似乎更脆弱,并且只会为我提供对控制器操作的保护,而且还可以确保安全还有其他服务.

For #1 I've created a custom annotation and am using filters to read the annotation and check access, although this seems to be more brittle and will only give me protection for controller actions, and it would be nice to also secure other services as well.

我发现了一些信息,但没有完整.

I've found bits an pieces of this information, but nothing complete.

THIS 讨论自定义 ACL 但仅针对新权限,而不是控制逻辑

THIS talks about customizing ACL but only for a new permission, not controlling the logic

THIS 谈论使用 SpEL,但是我想在方法运行之前进行检查,以确保不会发生未经授权的影响.

THIS talks about using SpEL, but I'd like to have checks before a method runs, to make sure that no effect takes place that would be unauthorized.

似乎最接近我想做的事情,但特定于 Spring Security 而不是 Grails - 我最大的挑战是将 applicationContext.xml 中的信息转换为 resources.groovy

THIS appears to be the closest to what I want to do, but is specific to Spring Security and not Grails - my biggest challenge is converting the information in applicationContext.xml into resources.groovy

预先感谢您的任何建议或意见!

Thanks in advance for any suggestions or advice you may have!

推荐答案

您应该能够使用 Spring Security 和 grails 轻松完成此操作.

You should be able to do this with spring security and grails without much trouble.

我过去曾用以下 2 种方式处理类似的任务.两者都需要提供 @PreAuthorize@PostAuthorize 注释的 spring 安全 ACL 插件.

I used the following 2 ways in the past for similar tasks. Both require the spring security ACL plugin which provides the @PreAuthorize and @PostAuthorize annotations.

自定义权限评估器

您可以在安全注释中使用 hasPermission() 方法并创建自定义 PermissionEvaluator.在代码中,这看起来像这样:

You can use the hasPermission() methods within security annotations and create a custom PermissionEvaluator. Within code this looks like this:

@PreAuthorize("hasPermission(#myObject, 'update')")
public void updateSomething(myObject) {
  ..
}

hasPermission() 调用由 Spring Security 路由到 PermissionEvaluator.要编写自己的实现,您必须实现 PermissionEvaluator 接口:

The hasPermission() calls are routed to a PermissionEvaluator by spring security. To write your own implementation you have to implement the PermissionEvaluator interface:

class MyPermissionEvaluator implements PermissionEvaluator {

    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        // your custom logic..
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        // your custom logic
    }
}

要注册您的PermissionEvaluator,您必须覆盖名为expressionHandler 的bean.为此,您可以在 conf/spring/resources.groovy 中添加以下几行:

To register your PermissionEvaluator you have to override the bean named expressionHandler. You do this by adding the following lines in conf/spring/resources.groovy:

beans = {

    expressionHandler(MyExpressionHandler) {
        parameterNameDiscoverer = ref('parameterNameDiscoverer')
        permissionEvaluator = ref('myPermissionEvaluator') // your PermissionEvaluator
        roleHierarchy = ref('roleHierarchy')
        trustResolver = ref('authenticationTrustResolver')
    }

    myPermissionEvaluator(MyPermissionEvaluator)

}

resources.groovy 中,您可以像使用 spring 时在 applicationContext.xml 中所做的那样定义 bean.以上几行创建了一个 MyPermissionEvaluator 类型的 bean,bean 名称为 myPermissionEvaluator.Spring 证券 expressionHandler bean 被 MyExpressionHandler 类型的 bean 覆盖.其他依赖从spring security ACL插件的配置文件复制过来.

Within resources.groovy you can define beans like you would do in applicationContext.xml when using spring. The above lines create a bean of type MyPermissionEvaluator with the bean name myPermissionEvaluator. Spring securities expressionHandler bean is overridden with a bean of type MyExpressionHandler. The other dependencies are copied from the configuration file of the spring security ACL plugin.

安全注释中的服务调用

如果 hasPermission() 方法的设计不能满足您的所有要求,您可以改用简单的服务调用.@PostAuthorize@PreAuthorize 注释使用 SPEL 来评估表达式.在 SPEL 中,您可以使用 @ 符号来访问 bean.例如:

If the design of the hasPermission() methods does not achive all you requirements you can use simple service calls instead. The @PostAuthorize and @PreAuthorize annotations use SPEL to evaluate the expression. Within SPEL you can use the @ symbol to access beans. For example:

@PreAuthorize("@securityService.canAccess(#myObject)")
public void doSomething(myObject) {
  ..
}

这将调用名为 securityService 的 bean 的 canAccess 方法并将方法参数传递给它.

This calls the canAccess method of the bean named securityService and passes the method argument to it.

要使用这种方法,您必须注册一个 BeanResolver评估上下文.为此,您必须覆盖 DefaultMethodSecurityExpressionHandler 由 spring 安全 ACL 插件配置.

To use this approach you have to register a BeanResolver on the EvaluationContext. To do this you have to override the DefaultMethodSecurityExpressionHandler which is configured by the spring security ACL plugin.

这可能如下所示:

class MyExpressionHandler extends DefaultMethodSecurityExpressionHandler {

    BeanResolver beanResolver

    @Override
    public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {
        StandardEvaluationContext ctx = (StandardEvaluationContext) super.createEvaluationContext(auth, mi)
        ctx.setBeanResolver(beanResolver) // set BeanResolver here
        return ctx;
    }    
}

BeanResolver 是一个将 bean 名称解析为 bean 实例的简单接口:

BeanResolver is a simple interface that resolves a bean name to a bean instance:

class GrailsBeanResolver implements BeanResolver {

    GrailsApplication grailsApplication

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

}

最后将 bean 添加到 resources.groovy:

And finally add the beans to resources.groovy:

expressionHandler(MyExpressionHandler) {
    parameterNameDiscoverer = ref('parameterNameDiscoverer')
    permissionEvaluator = ref('permissionEvaluator')
    roleHierarchy = ref('roleHierarchy')
    trustResolver = ref('authenticationTrustResolver')
    beanResolver = ref('beanResolver') // this is your BeanResolver
}

// This is the service called within security expressions
// If you place your service in the grails service folder you can skip this line
securityService(MySecurityService) 

// this is your BeanResolver
beanResolver(GrailsBeanResolver) {
    grailsApplication   = ref('grailsApplication')
}

更新 (2013-10-22):最近我写了一个博客文章 正是关于这一点,它提供了一些额外的信息.

Update (2013-10-22): Recently I wrote a blog post about exactly this which provides some additional information.

这篇关于Grails 自定义安全评估器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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