4

I'm new in the Spring's world I'm using Spring Boot 1.2.5 with Spring Security 3.1.2. Due to my project's requirements I need to configure an ACL security model. I have the following java class configuration:

@Configuration
public class ACLConfig {

    @Autowired
    DataSource dataSource;


    @Bean
    JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource);
    }

    @Bean
    DataSourceTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    EhCacheBasedAclCache aclCache() {
        EhCacheFactoryBean factoryBean = new EhCacheFactoryBean();
        EhCacheManagerFactoryBean cacheManager = new   EhCacheManagerFactoryBean();
        cacheManager.setAcceptExisting(true);
      cacheManager.setCacheManagerName(CacheManager.getInstance().getName());
        cacheManager.afterPropertiesSet();

        factoryBean.setName("aclCache");
        factoryBean.setCacheManager(cacheManager.getObject());
        factoryBean.setMaxBytesLocalHeap("16M");
        factoryBean.setMaxEntriesLocalHeap(0L);
        factoryBean.afterPropertiesSet();
        return new EhCacheBasedAclCache(factoryBean.getObject());
    }

    @Bean
    LookupStrategy lookupStrategy() {
        return new BasicLookupStrategy(dataSource, aclCache(),  aclAuthorizationStrategy(), new ConsoleAuditLogger());
    }

    @Bean
    AclAuthorizationStrategy aclAuthorizationStrategy() {
        return new AclAuthorizationStrategyImpl(new  SimpleGrantedAuthority("ROLE_SUPER_ADMIN"),
        new SimpleGrantedAuthority("ROLE_SUPER_ADMIN"),
        new SimpleGrantedAuthority("ROLE_SUPER_ADMIN"));
    }

    @Bean
    JdbcMutableAclService aclService() {
        JdbcMutableAclService service = new     JdbcMutableAclService(dataSource, lookupStrategy(), aclCache());
        service.setClassIdentityQuery("select currval(pg_get_serial_sequence('acl_class', 'id'))");
        service.setSidIdentityQuery("select currval(pg_get_serial_sequence('acl_sid', 'id'))");
        return service;
    }

    @Bean
    AclEntryVoter aclDeleteVoter()
    {
        AclEntryVoter voter = new   AclEntryVoter(aclService(),"ACL_NOMCITY_DELETE", new Permission[]  {BasePermission.DELETE});
        voter.setProcessDomainObjectClass(NomCity.class);
        return voter;
    }

    @Bean
    AclEntryVoter aclUpdateVoter()
    {
        return new AclEntryVoter(aclService(),"ACL_NOMCITY_UPDATE", new   Permission[]{BasePermission.ADMINISTRATION});
    }

    @Bean
    AclEntryVoter aclReadVoter()
    {
        return new AclEntryVoter(aclService(),"ACL_NOMCITY_READ", new   Permission[]{BasePermission.READ});
    }

    @Bean
    AccessDecisionManager accessDecisionManager (){

        List<AccessDecisionVoter<? extends Object>> list = new ArrayList<>();
        list.add(aclDeleteVoter());
        list.add(aclReadVoter());
        list.add(aclUpdateVoter());
        return new AffirmativeBased(list);
    }

}

I have the following RestController's methods, it use the ACLs defined earlier:

@RequestMapping(value = "/nomCitys",
        method = RequestMethod.POST,
        produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
@Transactional
@Secured({"ROLE_ADMIN","ROLE_USER"})
public ResponseEntity<NomCity> create(@Valid @RequestBody NomCity nomCity) throws URISyntaxException {

    NomCity result = nomCityRepository.save(nomCity);

    User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    ObjectIdentity oi = new ObjectIdentityImpl(NomCity.class,result.hashCode());
    MutableAcl acl = mutableAclService.createAcl(oi);

    acl.insertAce(0, BasePermission.ADMINISTRATION, new GrantedAuthoritySid("ROLE_ADMIN"), true);
    acl.insertAce(1, BasePermission.DELETE, new PrincipalSid(user.getUsername()), true); 
    acl.insertAce(2, BasePermission.READ, new GrantedAuthoritySid("ROLE_USER"), true);

    mutableAclService.updateAcl(acl);

    return ResponseEntity.created(new URI("/api/nomCitys/" + result.getId()))
            .headers(HeaderUtil.createEntityCreationAlert("nomCity", result.getId().toString()))
            .body(result);
}

When I create a new city the following ACL entries are created too:

  • The user with ROLE_ADMIN role have Admin permission.
  • The user how create the city have Delete permission.
  • The user with ROLE_USER role can read the city.

The following method is the delete method:

@RequestMapping(value = "/nomCitys/{id}",
        method = RequestMethod.DELETE,
        produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
@Transactional
@Secured("ACL_NOMCITY_DELETE")
public ResponseEntity<Void> delete(@PathVariable Long id) {

    nomCityRepository.delete(id);

    ObjectIdentity oid = new ObjectIdentityImpl(NomCity.class,id);
    mutableAclService.deleteAcl(oid, true);

    return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert("nomCity", id.toString())).build();
}

When I create a new city all work fine, the ACL entries are created and stored in the data base, but when I go to remove a city I get a 403, although I'm logging with the user who created the city, reviewing some pages I saw the following xml entry:

<security:global-method-security
  secured-annotations="enabled" access-decision-manager  ref="customAccessDecisionManager" />

I suppose that it register the AccessDecisionManager but I don't know how do the same using Java Config and I don't if it's the reason of all my problems.

JCF
  • 368
  • 3
  • 15

1 Answers1

0

This question is for @secure anotation, but I finally solve the problem make a class configuration for using @Pre and @Post anotation, I post a config java class in my answer for this question.

Community
  • 1
  • 1
JCF
  • 368
  • 3
  • 15