1

I am trying to implement Spring Security ACL in my application. I have many classes that I want to use an ACL on.

I read in the documentation that AOP have been used with success before. Does this mean that all the services should have a common interface for doing CRUD against the objects for maximum reuse of the advise?

Or is it normal to manually insert, delete, ... in the save, update, delete methods of the service?

I can't manage to find many examples of how people use the framework.

LuckyLuke
  • 47,771
  • 85
  • 270
  • 434

2 Answers2

2

---- Listener for Entity removal (includes cascading deletes) -----

package com.acme.model.aspects;

import javax.annotation.PostConstruct;
import javax.persistence.PreRemove;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.data.domain.Persistable;

import com.acme.PermissionService;

@Component
public class ObjectIdentityListener {

    private static final Logger LOG = LoggerFactory.getLogger(ObjectIdentityListener.class);

    static private PermissionService permissionService;

    @Autowired(required = true)
    @Qualifier("permissionService")
    public void setSearchService(PermissionService _permissionService)
    {
        permissionService = _permissionService;
    }

    @PreRemove
    public void preRemove(Object object) {
        if(object instanceof Persistable) {
            LOG.info("Deleting object identity for class {} id {} ", persistable.getClass(), persistable.getId());
            permissionService.deleteObjectIdentity((Persistable) object);
        }
    }

    @PostConstruct
    public void init() {
        Assert.notNull(permissionService, "'permissionService' is required");
    }
}

---- Delete method for permissionService ----

public void deleteObjectIdentity(Persistable persistable) {
    try{
        MutableAcl acl = (MutableAcl) mutableAclService.readAclById(identity(persistable));
        mutableAclService.deleteAcl(acl.getObjectIdentity(), true);
    } catch (NotFoundException e){
        LOG.info("Could not find ACL for target {}", persistable);
    }
}
SergeyB
  • 9,478
  • 4
  • 33
  • 47
  • Would you mind taking a look at that? http://stackoverflow.com/questions/21388977/granting-permission-in-spring-security-acl – LuckyLuke Jan 27 '14 at 19:04
1

It all depends on your app. Having a centralized hierarchy of services would certainly make it simpler to implement single security checks for create/retrieve/update/delete methods. But you have an existing app with different services that don't necessarily have a common parent implementation, then you'd have to add ALC security annotation on each service method.

Another option is to put ACL security on your DAO layer, it works fine, but for some reason just doesn't feel right. IMHO DAO's shouldn't deal with things like security. I've spent a LOT of time dealing with Spring Security ACL, got a pretty good handle on it by now, ping me if you need any concrete examples.

SergeyB
  • 9,478
  • 4
  • 33
  • 47
  • What I had in mind when I asked the question was how I should insert/update/delete the records that ACL need. I have CRUD operations in the existing services for the domain objects. You need to keep the ACL entries in sync with the domain objects right? How do you manage that? Do you add ACL code for inserting/updating/deleting in these service methods, or do you use AOP as the documentation suggest you can do? Any examples on this? – LuckyLuke Jan 24 '14 at 22:17
  • I know you can do security checks using AOP, but I haven't seen anything that would create/update/delete them for you. Spring Security ACL's MutableAclService gives you all the methods you'd need to CRUD ACL entries. I wrote a wrapper class around the MutableAclService to hide some of the ACL specifics, and then call it from my parent CRUD service. In CRUD service's save, call wrapperSercurityService.grantPermission(Object target, Object recipient, Permission permission). In delete method, call wrapperSercurityService.removePermission(Object target, Object recipient, Permission permission). – SergeyB Jan 24 '14 at 23:03
  • Good, that was how I thought I could do it. I may have some few other questions while I am implementing it. Thank you for helping me ;) – LuckyLuke Jan 25 '14 at 09:03
  • #1: How do you deal with cascading? In your domain model you use JPA/programmatically cascading. How do you ensure that deletion of an object also removes all ACL entries of the relation to that domain object? Is it not crucial? – LuckyLuke Jan 25 '14 at 09:30
  • @LuckyLuke - glad to be of help. Posted example implementation as another answer to this question. – SergeyB Jan 25 '14 at 16:03
  • Hi Ike,I need complete example so please can you send me this concrete example.My Id is satish.dhiman025@gmail.com – Satish Dhiman Mar 19 '14 at 05:28
  • @SatishDhiman - for examples consult https://github.com/spring-projects/spring-security/tree/master/samples – SergeyB Mar 19 '14 at 15:09