Grails Security Assessment Specialist

I am working on an application that must perform security checks at the object level, and the checks will be performed by the service, because it will need to make REST calls to a separate application. Because of this, I cannot use Spring security roles or ACLs because none of this data will be stored locally in the application. I am trying to find an elegant way to handle this, and here are two options that I can think of:

1) Create a custom annotation that will check permissions

2) Extend the Spring Security Annotation permission check (perhaps using a permission analyzer?), Which allows me to write the logic for access control

For # 1, I created a custom annotation and use filters to read the annotation and access control, although this seems more fragile and will only protect the controller's actions, and it would be nice to provide security for other services as well.

I found fragments of this information, but did not complete anything.

THIS talks about setting up an ACL, but only for a new resolution, not for managing logic

THIS says about using SpEL, but I would like to have checks before running the method to make sure that there is no effect that would be unauthorized.

THIS seems to be closest to what I want to do, but is of particular importance to Spring Security and not Grails - my biggest problem is converting the information in applicationContext.xml to resources.groovy

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

+4
source share
1 answer

You can do this with spring security and the grail without any problems.

I have used the following two methods in the past for similar tasks. Both require the spring ACL plugin, which provides @PreAuthorize and @PostAuthorize .

Custom PermissionEvaluator

You can use the hasPermission() methods in security annotations and create a custom PermissionEvaluator . Inside the code, it looks like this:

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

The hasPermission() calls hasPermission() routed to the PermissionEvaluator security service on spring. To write your own implementation, you must 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 must override the bean named expressionHandler . You do this by adding the following lines to conf/spring/resources.groovy :

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

Inside resources.groovy you can define beans, as you would in applicationContext.xml when using spring. The above lines create a bean of type MyPermissionEvaluator named bean MyPermissionEvaluator . spring securities expressionHandler bean is overridden by a bean of type MyExpressionHandler . Other dependencies are copied from the spring ACL plugin configuration file.

Service Calls in Security Annotations

If the design of the hasPermission() methods does not fulfill all your requirements, you can use simple utility calls instead. The annotations @PostAuthorize and @PreAuthorize use SPEL to evaluate the expression. In SPEL, you can use the @ symbol to access beans. For instance:

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

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

To use this approach, you need to register the BeanResolver with an EvaluationContext . To do this, you need to override the DefaultMethodSecurityExpressionHandler , which is configured by the spring ACL plugin.

It might look like this:

 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 the 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 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 stating that this is what gives some additional information.

+9
source

Source: https://habr.com/ru/post/1492723/


All Articles