Spring Security的ACL配置问题

时间:2015-08-25 16:38:18

标签: java spring spring-security

我是Spring的新世界,我正在使用带有Spring Security 3.1.2的Spring Boot 1.2.5。由于我的项目要求,我需要配置ACL安全模型。我有以下java类配置:

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

}

我有以下RestController的方法,它使用前面定义的ACL:

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

创建新城市时,也会创建以下ACL条目:

  • 具有ROLE_ADMIN角色的用户具有管理员权限。
  • 用户如何创建城市具有删除权限。
  • 具有ROLE_USER角色的用户可以阅读该城市。

以下方法是删除方法:

@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();
}

当我创建一个新的城市一切正常时,ACL条目被创建并存储在数据库中,但当我去删除一个城市时,我得到403,尽管我正在与创建城市的用户一起登录,查看我看到以下xml条目的一些页面:

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

我想它注册了AccessDecisionManager,但是我不知道如何使用Java Config,如果这是我所有问题的原因,我不知道。

1 个答案:

答案 0 :(得分:0)

这个问题适用于@secure anotation,但是我终于解决了使用@Pre和@Post anotation进行类配置的问题,我在这个question的答案中发布了一个配置java类。