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

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

问题描述

我正在研究一个必须进行对象级安全检查的应用程序,并且检查将由服务完成,因为它需要将REST调用到单独的应用程序。因此,我无法使用Spring Security角色或ACL,因为这些信息都不会存储在本地应用程序中。我试图找到一个优雅的方式来处理这个问题,这里有两个选项我可以想到:


$ b <1>创建一个自定义注释来检查权限

p>

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

对于#1,我创建了一个自定义注释,并使用过滤器来读取注释并检查访问权限,虽然这看起来更脆弱,并且只能为控制器操作提供保护,并且也很安全其他服务也是如此。



我发现这些信息有点片断,但没有完成。



这篇讲述了如何定制ACL,但仅限于新的权限,而不是控制逻辑

这篇讲述了使用SpEL,但我希望在方法运行之前进行检查,以确保不会发生未经授权的影响。



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



谢谢您可以事先提出任何建议或建议! 解决方案

你应该可以用spring security和grails来做这件事,麻烦。



过去我采用了以下两种方法来完成类似的任务。两者都需要提供 @PreAuthorize @PostAuthorize 注释的spring security ACL插件。



自定义PermissionEvaluator



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

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

<$ spring安全性将c $ c> hasPermission()调用路由到 PermissionEvaluator 。要编写自己的实现,您必须实现 PermissionEvaluator 接口:

  class MyPermissionEvaluator implements PermissionEvaluator {

@Override
public boolean hasPermission(Authentication authentication,Object targetDomainObject,Object permission){
//您的自定义逻辑..
}
$ b b @Override
public boolean hasPermission(身份验证,可序列化的targetId,字符串targetType,对象权限){
//您的自定义逻辑
}
}

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

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

myPermissionEvaluator(MyPermissionEvaluator)

}

resources.groovy 中,您可以定义像您这样的bean在使用spring时会在 applicationContext.xml 中执行。以上各行创建一个bean类型为 MyPermissionEvaluator 的bean,其名称为 myPermissionEvaluator 。 Spring证券 expressionHandler bean将被一个 MyExpressionHandler 类型的bean覆盖。其他依赖项是从Spring Security ACL插件的配置文件中复制的。



安全注释中的服务调用



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

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

}

这会调用 canAccess bean的名称为 securityService 的方法,并将方法参数传递给它。



要使用此方法,您必须注册一个 BeanResolver 上的 EvaluationContext 。要做到这一点,你必须重写 DefaultMethodSecurityExpressionHandler ,它由spring security ACL插件配置。



这看起来像下面这样:

  class MyExpressionHandler extends DefaultMethodSecurityExpressionHandler {

BeanResolver beanResolver

@Override
public EvaluationContext createEvaluationContext(认证auth,MethodInvocation mi){
StandardEvaluationContext ctx =(StandardEvaluationContext)super.createEvaluationContext(auth,mi)
ctx.setBeanResolver(beanResolver)//在这里设置BeanResolver
return ctx;


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

  class GrailsBeanResolver实现BeanResolver {

GrailsApplication grailsApplication
$ b $ @覆盖
public Object resolve(EvaluationContext evaluationContext,String beanName)throws AccessException {
return grailsApplication.mainContext.getBean(beanName)
}


最后将bean添加到 resources.groovy

  expressionHandler(MyExpressionHandler){
parameterNameDiscoverer = ref('参数名称发现者')
permissionEvaluator = ref('permissionEvaluator')
roleHierarchy = ref('roleHierarchy')
trustResolver = ref('authenticationTrustResolver')
beanResolver = ref('beanResolver' )//这是你的BeanResolver
}

//这是安全表达式中调用的服务
//如果将服务放在grails服务文件夹中,可以跳过这一行
securityService(MySecurityService)

//这是你的BeanResolver
beanResolver(GrailsBeanResolver){
grailsApplication = ref('grailsApplication')
}

更新(2013-10-22):最近我写了博文,其中提供了一些额外信息。


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) Create a custom annotation that will check permissions

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

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 talks about customizing ACL but only for a new permission, not controlling the logic

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.

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!

解决方案

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

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.

Custom 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) {
  ..
}

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

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)

}

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.

Service calls in security annotations

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

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

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.

This can look like the following:

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

}

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

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

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

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